[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Container infrastructure](index.md) > Managed Service for Kubernetes > Using Cloud Marketplace products > Integration with Argo CD

# Integrating Yandex Managed Service for Kubernetes with Argo CD

# Integration with Argo CD


[Argo CD](https://argo-cd.readthedocs.io) is a declarative GitOps tool for continuous delivery to Kubernetes.

This tutorial describes how to set up integration between a [Yandex Managed Service for GitLab instance](../../managed-gitlab/concepts/index.md#instance) and a [Managed Service for Kubernetes cluster](../../managed-kubernetes/concepts/index.md#kubernetes-cluster) running [Argo CD](https://yandex.cloud/en/marketplace/products/yc/argo-cd) and [GitLab Runner](https://yandex.cloud/en/marketplace/products/yc/gitlab-runner) to build Docker containers with [Kaniko](https://github.com/GoogleContainerTools/kaniko).

To integrate Argo CD with Managed Service for Kubernetes and Managed Service for GitLab:

1. [Create a GitLab instance](#create-gitlab).
1. [Configure GitLab](#configure-gitlab).
1. [Create a GitLab Runner](#runners).
1. [Set up an application repository for deployment](#setup-repo).
1. [Deploy your application using Argo CD](#deploy-argo).

If you no longer need the resources you created, [delete them](#clear-out).


## Required paid resources {#paid-resources}

The support cost for this solution includes:

* Fee for using the master and outgoing traffic in a Managed Service for Kubernetes cluster (see [Managed Service for Kubernetes pricing](../../managed-kubernetes/pricing.md)).
* Fee for using computing resources, OS, and storage in cluster nodes (VMs) (see [Compute Cloud pricing](../../compute/pricing.md)).
* Fee for public IP addresses assigned to cluster nodes (see [Virtual Private Cloud pricing](../../vpc/pricing.md#prices-public-ip)).
* Fee for a NAT gateway when used instead of public IP addresses for cluster nodes (see [Virtual Private Cloud pricing](../../vpc/pricing.md#nat-gateways)).
* Fee for Container Registry [storage](../../container-registry/pricing.md).
* GitLab instance fee that depends on the instance creation method:

   * Managed Service for GitLab: You pay for VM resources, data and backup storage, and the amount of outgoing traffic (see [Managed Service for GitLab pricing](../../managed-gitlab/pricing.md)).
   * VM with the GitLab image: You pay for VM resources, GitLab image, VM public IP address (see [Compute Cloud](../../compute/pricing.md) and [Virtual Private Cloud pricing](../../vpc/pricing.md#nat-gateways)).


## Getting started {#before-you-begin}

### Set up your infrastructure {#deploy-infrastructure}

{% list tabs group=instructions %}

- Manually {#manual}

  1. If you do not have a [network](../../vpc/concepts/network.md#network) yet, [create one](../../vpc/operations/network-create.md).
  1. If you do not have any [subnets](../../vpc/concepts/network.md#subnet) yet, [create them](../../vpc/operations/subnet-create.md) in the [availability zones](../../overview/concepts/geo-scope.md) where the new Managed Service for Kubernetes cluster and [node group](../../managed-kubernetes/concepts/index.md#node-group) will reside.
  1. [Create these service accounts](../../iam/operations/sa/create.md):
     * Service account for Kubernetes resources with the `k8s.clusters.agent` and `vpc.publicAdmin` [roles](../../managed-kubernetes/security/index.md#yc-api) for the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) to host the new Managed Service for Kubernetes cluster.
     * Service account for Managed Service for Kubernetes nodes with the [container-registry.images.puller](../../container-registry/security/index.md#container-registry-images-puller) and [container-registry.images.pusher](../../container-registry/security/index.md#container-registry-images-pusher) roles. The Managed Service for Kubernetes nodes will use this service account to push the [Docker images](../../container-registry/concepts/docker-image.md) built in GitLab to the [registry](../../container-registry/concepts/registry.md) and pull them to run [pods](../../managed-kubernetes/concepts/index.md#pod).

     {% note tip %}

     You can use the same service account to manage your Managed Service for Kubernetes cluster and its node groups.

     {% endnote %}

  1. [Create security groups](../../managed-kubernetes/operations/connect/security-groups.md) for the Managed Service for Kubernetes cluster and its node groups.

        {% note warning %}
        
        The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
        
        {% endnote %}

  1. [Create a security group](../../managed-gitlab/operations/configure-security-group.md) for the [Managed Service for GitLab instance](../../managed-gitlab/concepts/index.md#instance).
  1. [Create a Managed Service for Kubernetes cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-create.md) and [node group](../../managed-kubernetes/operations/node-group/node-group-create.md). When creating a Managed Service for Kubernetes cluster, specify the previously created service accounts for resources and nodes, as well as the security groups for the cluster.
  1. [Create a Yandex Container Registry](../../container-registry/operations/registry/registry-create.md).
  1. [Save the registry ID](../../container-registry/operations/registry/registry-list.md#registry-get), as you will need it at the next steps.

- Terraform {#tf}

  1. If you do not have Terraform yet, [install it](../infrastructure-management/terraform-quickstart.md#install-terraform).
  1. [Get the authentication credentials](../infrastructure-management/terraform-quickstart.md#get-credentials). You can add them to environment variables or specify them later in the provider configuration file.
  1. [Configure and initialize a provider](../infrastructure-management/terraform-quickstart.md#configure-provider). There is no need to create a provider configuration file manually, you can [download it](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
  1. Place the configuration file in a separate working directory and [specify the parameter values](../infrastructure-management/terraform-quickstart.md#configure-provider). If you did not add the authentication credentials to environment variables, specify them in the configuration file.

  1. Download the [k8s-argocd.tf](https://github.com/yandex-cloud-examples/yc-mk8s-argo-cd/blob/main/k8s-argocd.tf) Managed Service for Kubernetes cluster configuration file to the same working directory. This file describes:
     * [Network](../../vpc/concepts/network.md#network).
     * [Subnet](../../vpc/concepts/network.md#subnet).
     * Managed Service for Kubernetes cluster.
     * [Service account](../../iam/concepts/users/service-accounts.md) for Managed Service for Kubernetes resources and nodes.
     * Container Registry.
     * [Security groups](../../vpc/concepts/security-groups.md) which contain [rules](../../managed-kubernetes/operations/connect/security-groups.md) required for the Managed Service for Kubernetes cluster and its node groups.

        These security groups also include the rules required for the Managed Service for GitLab instance and [Container Registry](../../container-registry/concepts/registry.md).

        {% note warning %}
        
        The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
        
        {% endnote %}

  1. Specify the following in the configuration file:
     * [Folder ID](../../resource-manager/operations/folder/get-id.md).
     * [Kubernetes version](../../managed-kubernetes/concepts/release-channels-and-updates.md) for the Managed Service for Kubernetes cluster and node groups.
     * Managed Service for Kubernetes cluster CIDR.
     * Name of the service account for Managed Service for Kubernetes resources and nodes.
     * Name of the Container Registry.
  1. Validate your Terraform configuration files using this command:

     ```bash
     terraform validate
     ```

     Terraform will display any configuration errors detected in your files.
  1. Create the required infrastructure:

     1. Run this command to view the planned changes:
     
        ```bash
        terraform plan
        ```
     
        If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
     
     1. If everything looks correct, apply the changes:
        1. Run this command:
     
           ```bash
           terraform apply
           ```
     
        1. Confirm updating the resources.
        1. Wait for the operation to complete.

     All the required resources will be created in the specified folder. You can check resource availability and their settings in the [management console](https://console.yandex.cloud).

{% endlist %}

{% note warning %}

Do not change or delete Virtual Private Cloud resources used by the Managed Service for Kubernetes cluster. This may cause cluster errors or make it impossible to delete later.

{% endnote %}

### Install additional dependencies {#prepare}

Install the following tools in the local environment:
* [Yandex Cloud command line interface (YC CLI)](../../cli/operations/install-cli.md)
* [jq](https://stedolan.github.io/jq/)
* [Helm](https://helm.sh/docs/intro/install/)
* [Install kubect](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [configure it to work with the new cluster](../../managed-kubernetes/operations/connect/index.md#kubectl-connect).

## Create a GitLab instance {#create-gitlab}

Create either a [Managed Service for GitLab instance](../../managed-gitlab/concepts/index.md#instance) or a [VM](../../compute/concepts/vm.md) with a [GitLab image](../../compute/concepts/image.md) in the same [cloud network](../../vpc/concepts/network.md#network) as the [Managed Service for Kubernetes cluster](../../managed-kubernetes/concepts/index.md#kubernetes-cluster).

{% list tabs group=gl_installation %}

- Managed Service for GitLab instance {#instance-mgl}

  Create a Managed Service for GitLab instance by following [this guide](../../managed-gitlab/quickstart.md#instance-create).

- VM with a GitLab image {#gl-image-vm}

  Launch GitLab on a VM with a [public IP address](../../vpc/concepts/address.md#public-addresses).

  1. On the [folder dashboard](../../resource-manager/concepts/resources-hierarchy.md#folder) in the [management console](https://console.yandex.cloud), click **Create resource** and select `Virtual machine instance`.
  1. Under **Boot disk image**, in the **Product search** field, enter `Gitlab` and select a public [GitLab](https://yandex.cloud/en/marketplace/products/yc/gitlab) image.
  1. Under **Location**, select the [availability zone](../../overview/concepts/geo-scope.md) where your VM will reside. If you are not sure which one to choose, leave the default.
  1. Under **Computing resources**, navigate to the `Custom` tab and specify the [platform](../../compute/concepts/vm-platforms.md), number of vCPUs, and amount of RAM:
  
      * **Platform**: `Intel Ice Lake`.
      * **vCPU**: `4`.
      * **Guaranteed vCPU performance**: `100%`.
      * **RAM**: `8 GB`.
  
  1. Under **Network settings**:
      
      * In the **Subnet** field, select the network and subnet to connect your VM to. If the relevant [network](../../vpc/concepts/network.md#network) or [subnet](../../vpc/concepts/network.md#subnet) is missing, [create it](../../vpc/operations/subnet-create.md).
      * In the **Public IP address** field, keep `Auto` to assign the VM a random external IP address from the Yandex Cloud pool or select a static address from the list if you reserved one in advance.
  
  1. Under **Access**, select **SSH key** and specify the VM access credentials:
  
      * In the **Login** field, enter the username. Do not use `root` or other OS-reserved usernames. To perform operations requiring root privileges, use the `sudo` command.
      * In the **SSH key** field, select the SSH key saved in your [organization user](../../organization/concepts/membership.md) profile.
        
        If there are no SSH keys in your profile or you want to add a new key:
        
        1. Click **Add key**.
        1. Enter a name for the SSH key.
        1. Select one of the following:
        
            * `Enter manually`: Paste the contents of the public SSH key. You need to [create](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.
            * `Load from file`: Upload the public part of the SSH key. You need to create an SSH key pair on your own.
            * `Generate key`: Automatically create an SSH key pair.
            
              When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the `/home/<user_name>/.ssh` directory. In Windows, unpack the archive to the `C:\Users\<user_name>/.ssh` directory. You do not need additionally enter the public key in the management console.
        
        1. Click **Add**.
        
        The system will add the SSH key to your organization user profile. If the organization has [disabled](../../organization/operations/os-login-access.md) the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.
  
  1. Under **General information**, specify the VM name: `ci-tutorial-gitlab`.
  1. Click **Create VM**.
  
  It may take a few minutes to create your VM. When the VM status changes to `RUNNING` and GitLab starts, configure its settings.

{% endlist %}

## Configure GitLab {#configure-gitlab}

To configure GitLab and get ready for continuous integration (CI), create a new project and enter the CI authentication data:

{% list tabs group=gl_installation %}

- Managed Service for GitLab instance {#instance-mgl}

  1. Log in to the [Managed Service for GitLab instance](../../managed-gitlab/concepts/index.md#instance) web UI.
  1. Click **Create a project**.
  1. Click **Create blank project**.
  1. Fill out the fields as follows:
     * **Project name**: `gitlab-test`.
     * **Project URL**: Select the admin user in the field next to the Managed Service for GitLab instance FQDN.

     Leave the other fields unchanged.
  1. Click **Create project**.

- VM with a GitLab image {#gl-image-vm}

  1. On the Yandex Compute Cloud page, select the created [VM](../../compute/concepts/vm.md) and copy its [public IP](../../vpc/concepts/address.md#public-addresses).
  1. [Connect](../../compute/operations/vm-connect/ssh.md) to the VM over SSH.
  1. Get the GitLab administrator password with the following VM command:

     ```bash
     sudo cat /etc/gitlab/initial_root_password
     ```

  1. Copy the password without spaces from the `Password` line to the clipboard or a separate file.
  1. In your browser, open `http://<VM_public_IP_address>`. This will take you to the GitLab web UI.
  1. Log in as the administrator:
     * **Username or email**: `root`.
     * **Password**: Password you copied in the previous step.

     If you are unable to log in, [reset the administrator password](https://docs.gitlab.com/security/reset_user_password/#reset-your-root-password).
  1. [Change the administrator password](https://docs.gitlab.com/user/profile/user_passwords/#change-your-password).
  1. Log in as the administrator with the new password.
  1. Select **Create a project**.
  1. Specify the project name: `gitlab-test`.
  1. Click **Create project**.

{% endlist %}

## Create a GitLab Runner {#runners}

To run build tasks in your [Yandex Managed Service for Kubernetes cluster](../../managed-kubernetes/concepts/index.md#kubernetes-cluster), create a [GitLab Runner](https://docs.gitlab.com/runner/install/kubernetes/).To do this, install GitLab Runner by following [this guide](../../managed-kubernetes/operations/applications/gitlab-runner.md).

Once it is installed, you can run automated builds within your [Managed Service for Kubernetes cluster](../../managed-kubernetes/concepts/index.md#kubernetes-cluster).

For more information about installing and running GitLab Runner, see [this GitLab article](https://docs.gitlab.com/runner/install/).

## Set up an application repository for deployment {#setup-repo}

1. Get an [authorized key](../../iam/concepts/authorization/key.md) for the previously created service account with the `container-registry.images.puller` and `container-registry.images.pusher` roles:

   ```bash
   yc iam key create --service-account-name <name_of_service_account_for_nodes> -o key.json
   ```

1. Save the contents of the key to use it later:

   ```bash
   cat key.json | base64
   ```

1. Create [GitLab environment variables](https://docs.gitlab.com/ee/ci/variables/):
   1. In GitLab, navigate to **Settings** in the left-hand panel and select **CI/CD** from the pop-up list.
   1. Click **Expand** next to **Variables**.
   1. Add these environment variables:
      * `CI_REGISTRY`: Address of the previously created registry in `cr.yandex/<registry_ID>` format.
      * `CI_REGISTRY_USER`: `json_key`.
      * `CI_REGISTRY_PASSWORD`: Output of `cat key.json | base64`.

      To add a variable:
      1. Click **Add variable**.
      1. In the window that opens, specify the variable name in the **Key** field and its value in the **Value** field.
      1. Click **Add variable**.
1. Set up access to the repository:
   1. [Generate a new pair of SSH keys](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) or use an existing one.
   1. [Add a public part of the SSH key to the GitLab account settings](https://docs.gitlab.com/ee/user/ssh.html#add-an-ssh-key-to-your-gitlab-account).
1. Clone the repository:

   ```bash
   git clone git@<instance_name>.gitlab.yandexcloud.net:<admin_username>/gitlab-test.git
   ```

1. Clone the [yc-webinar-gitops-argo-crossplane](https://github.com/yandex-cloud-examples/yc-webinar-gitops-argo-crossplane) repository to your computer:

   ```bash
   git clone https://github.com/yandex-cloud-examples/yc-webinar-gitops-argo-crossplane.git
   ```

1. Copy all `yc-webinar-gitops-argo-crossplane/02-argocd/app` directory files, including hidden ones, to the `gitlab-test` directory:

   ```bash
   cp -rT <path_to_app_directory> <path_to_gitlab-test_directory>
   ```

1. Commit the changes to `gitlab-test` and push them to the repository:

   ```bash
   git add . && \
   git commit -m "Add app src and CI" && \
   git push
   ```

1. This will run the build script. To view its progress, in the left-hand panel in GitLab, select **Build** → **Pipelines**. Wait for both build steps to complete.
1. Open the completed build and copy the following line from the log (you will need it at the next step):

   ```text
   INFO[0025] Pushing image to cr.yandex/<registry_ID>/<admin_username>/gitlab-test:main.<commit_number>
   ```

## Deploy your application using Argo CD {#deploy-argo}

### Install Argo CD in the Managed Service for Kubernetes cluster {#install}

1. Install Argo CD by following [this guide](../../managed-kubernetes/operations/applications/argo-cd.md).

   {% note warning %}
   
   Kubernetes node groups require internet access to download images and components.
   
   You can provide internet access in the following ways:
   * By assigning a [public IP address](../../vpc/concepts/address.md#public-addresses) to each node in the group.
   * [By configuring a VM as a NAT instance](../routing/nat-instance/index.md).
   * [By setting up a NAT gateway](../../vpc/operations/create-nat-gateway.md).
   
   {% endnote %}

1. Get the admin password from the Kubernetes secret:

   ```bash
   kubectl --namespace <namespace> get secret argocd-initial-admin-secret \
     --output jsonpath="{.data.password}" | base64 -d
   ```

1. Set up ArgoCD port forwarding to your local computer:

   ```bash
   kubectl port-forward service/<Argo_CD_app_name>-argocd-server \
     --namespace <namespace> 8080:443
   ```

1. Open the Argo CD console at `https://127.0.0.1:8080` in your browser.
1. Log in to the console as `admin` using the password you got earlier.

### Add the GitLab repository to Argo CD {#create}

1. In GitLab, navigate to **Settings** in the left-hand panel and select **Access Tokens** from the drop-down list.
1. Create a new token with the following settings:
   * **Token name**: `argocd`.
   * **Select a role**: `Maintainer`.
   * **Select scopes**: `read_repository`.
1. Click **Create project access token**.
1. Copy the token value.
1. In the Argo CD console, go to **Settings** → **Repositories**.
1. Click **Connect Repo** and select **VIA HTTPS** from the list.

   {% note info %}

   If you get the `FATA[0000] rpc error: code = Unknown desc = error testing repository connectivity: authorization failed` error when connecting a repository, enable access to GitLab via HTTP(S).

   To enable access, in the left-hand panel in GitLab, select **Admin → Settings → General**. Under **Visibility and access controls**, find the **Enabled Git access protocols** setting and select the option that allows HTTP(S) access from the list.

   For more information, see [this GitLab guide](https://docs.gitlab.com/administration/settings/visibility_and_access_controls/#configure-enabled-git-access-protocols).

   {% endnote %}

1. In the form that opens, specify the following settings:
   * **Repository URL**: Repository URL in `https://<GitLab_instance_name>.gitlab.yandexcloud.net/<admin_username>/gitlab-test.git` format.
   * **Username**: `gitlab-ci-token`.
   * **Password**: Previously generated GitLab token.
1. Click **Connect**.
1. In the Argo CD console, go to **Applications** and click **Create Application**.
1. In the form that opens, specify the following settings:
   * **Application Name**: `gitlab-test`.
   * **Project**: `default`.
   * **Sync policy**: `Automatic`, then select **Prune resources** and **Self Heal**.
   * **Sync options**: Select `Auto-Create Namespace`.
   * **Repository URL**: Specify the repository URL in `https://<GitLab_instance_name>.gitlab.yandexcloud.net/<admin_username>/gitlab-test.git` format.
   * **Path**: `.helm`.
   * **Cluster URL**: `https://kubernetes.default.svc`.
   * **Namespace**: `gitlab-test`.
   * **image.repository**: `cr.yandex/<registry_ID>/<admin_username>/gitlab-test`.
   * **image.tag**: `main.<commit_number>`.
1. Click **Create** and wait for the synchronization to complete.
1. To check that the application is running, use the following command in the Managed Service for Kubernetes cluster:

   ```bash
   kubectl get all -n gitlab-test
   ```

   Result:

   ```text
   NAME                               READY   STATUS    RESTARTS   AGE
   pod/gitlab-test-67c8d58bc4-6w4q7   1/1     Running   0          2m26s
   pod/gitlab-test-67c8d58bc4-sldpc   1/1     Running   0          2m26s

   NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
   service/gitlab-test   ClusterIP   10.96.186.223   <none>        80/TCP    2m26s

   NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
   deployment.apps/gitlab-test   2/2     2            2           2m26s

   NAME                                     DESIRED   CURRENT   READY   AGE
   replicaset.apps/gitlab-test-67c8d58bc4   2         2         2       2m26s
   ```

### Test auto-syncing from the repository {#check}

1. Go to the directory with the [cloned project](#setup-repo) and open the `.helm/values.yaml` file.
1. Set `replicaCount` to `3`.
1. Save the changes and push them to the repository:

   ```bash
   git add . && \
   git commit -m "Increase replica count" && \
   git push
   ```

1. In the Argo CD console, wait for the app to synchronize.
1. Make sure the number of application pods in the Managed Service for Kubernetes cluster has increased:

   ```bash
   kubectl get pod -n gitlab-test
   ```

   Result:

   ```text
   NAME                               READY   STATUS    RESTARTS   AGE
   pod/gitlab-test-67c8d58bc4-6w4q7   1/1     Running   0          15m
   pod/gitlab-test-67c8d58bc4-7hmcn   1/1     Running   0          10m
   pod/gitlab-test-67c8d58bc4-sldpc   1/1     Running   0          15m

   NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
   service/gitlab-test   ClusterIP   10.96.186.223   <none>        80/TCP    15m

   NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
   deployment.apps/gitlab-test   3/3     3            3           15m

   NAME                                     DESIRED   CURRENT   READY   AGE
   replicaset.apps/gitlab-test-67c8d58bc4   3         3         3       15m
   ```

## Delete the resources you created {#clear-out}

Some resources are not free of charge. Delete the resources you no longer need to avoid paying for them:
1. [Delete the created Docker images](../../container-registry/operations/docker-image/docker-image-delete.md).
1. Delete the Managed Service for Kubernetes cluster and Container Registry:

   {% list tabs group=instructions %}

   - Manually {#manual}

     1. [Delete the Managed Service for Kubernetes cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-delete.md).
     1. [Delete the Container Registry](../../container-registry/operations/registry/registry-delete.md).
     1. [Delete the created subnets](../../vpc/operations/subnet-delete.md) and [networks](../../vpc/operations/network-delete.md).
     1. [Delete the created service accounts](../../iam/operations/sa/delete.md).

   - Terraform {#tf}

     1. In the terminal window, go to the directory containing the infrastructure plan.
     
         {% note warning %}
     
         Make sure the directory has no Terraform manifests with the resources you want to keep. Terraform deletes all resources that were created using the manifests in the current directory.
     
         {% endnote %}
     
     1. Delete resources:
     
         1. Run this command:
     
             ```bash
             terraform destroy
             ```
     
         1. Confirm deleting the resources and wait for the operation to complete.
     
         All the resources described in the Terraform manifests will be deleted.

   {% endlist %}

1. [Delete the GitLab VM](../../compute/operations/vm-control/vm-delete.md) or Managed Service for GitLab instance you created.