极狐GitLab整合K8S实现GitOps与CI/CD(Agent方式)

极狐GitLab整合K8S实现GitOps与CI/CD(Agent方式)

1. 简介

参考文档:

极狐GitLab Kubernetes Agent 是用安全和云原生方式实现极狐GitLab 与 Kubernetes 集成的组件,不同于老版本使用证书连接 Kubernetes 集群的方式。从 v14 版本开始,极狐gitlab 将逐渐废除使用证书连接 Kubernetes 集群的方式。

它实现的功能:

它包含两部分:

  • 服务端,位于极狐GitLab 一侧,简称:kas
  • 客户端,位于 k8s 一侧,简称:agentk

要基于 Agent 执行 GitOps 部署,需要满足下列条件:

  • 一个配置好的 k8s 集群,安装了 Agent 客户端;
  • 极狐GitLab 启用了 Agent 服务端;
  • 极狐GitLab 创建了 Agent 配置库和清单库;
    • 配置库和清单库可以合并成一个私有的仓库;
    • 如果配置库与清单库独立,那么配置库可以是私有,而清单库必须为公有;

注意:Kubernetes Agent 在 14.5 之前只支持 ee 以上收费版本,14.5 版本后虽然在 免费版本能够看到此功能,但是添加后使用 gitops 还是会出现错误:project not found,原因是清单文件的同步不是免费的、是专业版以上才能用,本教程使用极狐gitlab v14.7.3

2. 主要功能简介

本部分只是介绍 Agent 使用场景,没有实际操作步骤;

2.1 GitOps workflow

2.1.1 GitOps 简介

这里采用 RedHat 对 GitOps 的定义

  • GitOps 是一套使用 Git 来管理基础架构和应用配置的实践,GitOps 在运行过程中以 Git 为声明性基础架构和应用的单一事实来源。
  • GitOps 使用 Git 拉取请求来自动管理基础架构的置备和部署。Git 存储库包含系统的全部状态,因此系统状态的修改痕迹既可查看也可审计。

2.1.2 演示环境

  • 演示系统已启用 Kubernetes Agent;
    • 包括服务端和客户端;
  • 没有其它方式集成的 k8s;
    • 比如使用 k8s 密钥和 serviceAccount 集成的 k8s
  • 关联了一个 agent 到 gitops/agentk 项目;
    • 该仓库没有 CI/CD 配置文件 ( .gitlab-ci.yml )

2.1.3 演示效果

在该项目仓库里编写任意 k8s 对象的描述文件 (.yaml 或者 .json 格式),都能实时部署到 k8s 集群中,无需执行 ci/cd ;

2.2 CI/CD workflow

2.2.1 演示环境

在上述仓库中增加 ci/cd 配置文件:.gitlab-ci.yml

2.2.2 演示效果

  • 执行 ci/cd pipeline时,容器内注入了 KUBECONFIG 等 k8s 集群连接信息;
  • 可以在容器内执行 kubectl 、 helm 等命令连接 k8s集群再执行部署;

3. 启用 Kubernetes Agent

3.1 Omnibus 方式

首先,修改 /etc/gitlab/gitlab.rb 配置

gitlab_kas['enable'] = true

然后运行生效:gitlab-ctl reconfigure

3.2 helm chart 方式

helm upgrade --install gitlab gitlab/gitlab \
  --set global.kas.enabled=true
  • 默认启用

4. GitOps 演示

4.1 创建仓库

gitops/agentk

4.2 创建配置文件

gitops/agentk 库中创建:.gitlab/agents/agent1/config.yaml

gitops:
  manifest_projects:
  - id: "gitops/agentk"
    paths:
    - glob: '/**/*.{yaml,json}'
  • 上面配置的含义是 agent 名称为 agent1,指定项目为 gitops/agentk,指定资源清单文件为项目根目录下任何目录下的 yaml 和 json 为后缀的文件
  • 项目配置为列表,可以指定多个项目
  • 配置文件编写参考:Using a GitOps workflow for Kubernetes | GitLab

4.3 创建资源清单文件

定义 k8s 资源描述文件,例如:deploy/nginx.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: test-agent
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: test-agent
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

4.4 安装 Agent

操作步骤:

  • 进入项目菜单”基础架构 > Kubernetes 集群 > GitLab 托管集群”;
  • 点击 Install a new GitLab Agent;
  • 点击 Select an Agent 下拉框,选择在配置文件里定义的 Agent 名称;
  • 复制并执行弹出屏幕上的 Agent 安装命令

agent01

image-20220228121426324

**注意:如果安装命令的 --kas-address= 的地址结尾缺少斜线 /,必须手动添加后再执行,否则 agent 安装后无法连接到 kas **

$ docker run --pull=always --rm \
    registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate \
    --agent-token=ab7HZQiAzBuV2n-7cZoVeEi6jByjHRMzFQu1c_Mx_s8TQGWCJA \
    --kas-address=wss://gitlab.example.com/-/kubernetes-agent/ \
    --agent-version stable \
    --namespace gitlab-kubernetes-agent  > resources.yaml

# resources.yaml 就是 agent 的资源定义文件

$ kubectl apply -f resources.yaml

$ kubectl get pod -A|grep gitlab-agent
gitlab-kubernetes-agent   gitlab-agent-77475dcdd8-4lhcr             1/1     Running     0          39s
  • 这里测试环境 docker 版本 19.03 ,运行上面的命令会报错:unknown flag: --pull,去掉 --pull=always 即可

web 界面查看 agent 并未正常连接到极狐gitlab

image-20220228122523276

查看日志

$ kubectl -n gitlab-kubernetes-agent logs -f gitlab-agent-77475dcdd8-4lhcr
...
{"level":"error","time":"2022-02-28T04:25:38.901Z","msg":"Error handling a connection","mod_name":"reverse_tunnel","error":"Connect(): rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://gitlab.example.com/-/kubernetes-agent/\\\": dial tcp: lookup gitlab.example.com on 10.43.0.10:53: no such host\""}

原因是 pod 无法解析 gitlab.example.com,解决方法如下:

然后在集群 coredns 中添加 hosts 解析

$ kubectl -n kube-system edit configmaps coredns
...
apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        hosts /etc/coredns/NodeHosts {
          10.10.10.60 gitlab.example.com
          ttl 60    
          reload 15s 
          fallthrough
        }               
...

# 删除 coredns pod 生效
$ kubectl get pod -n kube-system
NAME                                      READY   STATUS      RESTARTS   AGE
helm-install-traefik-g4xsp                0/1     Completed   0          151m
metrics-server-86cbb8457f-8wghh           1/1     Running     0          151m
local-path-provisioner-5ff76fc89d-r87zg   1/1     Running     0          151m
coredns-854c77959c-nm28h                  1/1     Running     0          151m

$ kubectl -n kube-system delete pod coredns-854c77959c-nm28h
pod "coredns-854c77959c-nm28h" deleted

删除旧 pod ,重建新 pod 生效

kubectl -n gitlab-kubernetes-agent delete pod gitlab-agent-77475dcdd8-4lhcr

查看 pod 日志还是报错:

x509: certificate signed by unknown authority

原因是 ssl 证书是自签的,查看 resources.yaml 发现是使用的 registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:stable 运行 agent,查看帮助,发现使用 --ca-cert-file 可以解决

$ docker run --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:stable --help
GitLab Kubernetes Agent

Usage:
  agentk [flags]

Flags:
      --as string                      Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
      --as-group stringArray           Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
      --as-uid string                  UID to impersonate for the operation.
      --ca-cert-file string            Optional file with X.509 certificate authority certificate in PEM format
      --cache-dir string               Default cache directory (default "/home/nonroot/.kube/cache")
      --certificate-authority string   Path to a cert file for the certificate authority
      --client-certificate string      Path to a client certificate file for TLS
      --client-key string              Path to a client key file for TLS
      --cluster string                 The name of the kubeconfig cluster to use
      --context string                 The name of the kubeconfig context to use
  -h, --help                           help for agentk
      --insecure-skip-tls-verify       If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
      --kas-address string             GitLab Kubernetes Agent Server address
      --kubeconfig string              Path to the kubeconfig file to use for CLI requests.
  -n, --namespace string               If present, the namespace scope for this CLI request
      --request-timeout string         The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
  -s, --server string                  The address and port of the Kubernetes API server
      --tls-server-name string         Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
      --token string                   Bearer token for authentication to the API server
      --token-file string              File with access token
      --user string                    The name of the kubeconfig user to use
  -v, --version                        version for agentk
# 删除资源
kubectl delete -f resources.yaml

# 创建 gitlab.example.com 的证书 secret
kubectl create namespace gitlab-kubernetes-agent
kubectl -n gitlab-kubernetes-agent create secret generic gitlab.example.com.crt --from-file=gitlab.example.com.crt
# 也可以是签发 gitlab.example.com.crt 的根证书 ca.pem

编辑 resources.yaml 添加 secret 挂载

$ vi resources.yaml
...
      - args:
        - --ca-cert-file=/cafile/gitlab.example.com.crt
        - --token-file=/config/token
        - --kas-address
        - wss://gitlab.example.com/-/kubernetes-agent/
...
        volumeMounts:
        - mountPath: /cafile
          name: ca-file
...
      volumes:
      - name: ca-file
        secret:
          secretName: gitlab.example.com.crt
...

重新应用即可,pod 日志未看到报错

$ kubectl apply -f resources.yaml
$ kubectl get pod -A|grep gitlab-kubernetes-agent
gitlab-kubernetes-agent   gitlab-agent-7f7978db94-rfhql             1/1     Running     0          59s

但是在极狐gitlab web 界面上还是可以看到未正常连接

image-20220228122523276

查看 gitlab 主机上的 kas 服务侧日志发现一样证书报错,kas 无法正常连接极狐gitlab 实例

$ tail /var/log/gitlab/gitlab-kas/current
...
2022-02-28_06:27:25.40431 {"level":"error","time":"2022-02-28T14:27:25.404+0800","msg":"AgentInfo()","correlation_id":"01FWZFTJJTQCCG3SNHEPZ09DPW","grpc_service":"gitlab.agent.agent_configuration.rpc.AgentConfiguration","grpc_method":"GetConfiguration","error":"Get \"https://gitlab.example.com/api/v4/internal/kubernetes/agent_info\": x509: certificate signed by unknown authority"}

解决方法暂时只有极狐gitlab 使用有效机构颁发的有效证书即可。

image-20220228141343963

正常的话,这时候 k8s 集群会根据 deploy/nginx.yaml 创建相关资源

4.5 删除 Agent

可以在 web 界面删除(14.7 后才添加的功能)或者使用 graphql 删除,具体参考:Working with the agent for Kubernetes | GitLab

5. CI/CD 演示

还是在 gitops/agentk (已安装 agent )基础上进行

5.1 添加仓库

gitops/p1

5.2 添加 agent 认证

如果就是当前项目下(gitops/agentk)使用 agent,则不需要添加认证

编辑 gitops/agentk 项目 .gitlab/agents/agent1/config.yaml 添加

ci_access:
  projects:
  - id: gitops/p1
  • 必须是同组下的项目,最多 100 个

也可以添加组

ci_access:
  projects:
  - id: gitops/g1
  - id: gitops/g2
  • 必须是同组下面的子组,最多 100 个

5.3 添加 .gitlab-ci.yml

gitops/p1 下添加

stages:
  - build

build:
  stage: build
  image:
    name: bitnami/kubectl:1.20.7
    entrypoint: [""]
  script:
  - kubectl config get-contexts
  - kubectl config use-context gitops/agentk:agent1
  - kubectl get pod -A
  • 镜像 bitnami/kubectl:1.20.7 经常 pull 不下来,可能会导致 job 失败,可以尝试使用:cloudctl/kubectl:1.20.5

如果不添加前面的认证任务会报错:

$ kubectl config use-context gitops/agentk:agent1
error: no context exists with the name: "gitops/agentk:agent1"
ERROR: Job failed: command terminated with exit code 1

运行 job 发现报错:

...
$ kubectl config get-contexts
CURRENT   NAME           CLUSTER   AUTHINFO   NAMESPACE
          g2/p2:agent1   gitlab    agent:5    
$ kubectl config use-context g2/p2:agent1
Switched to context "g2/p2:agent1".
$ kubectl get pod
error: You must be logged in to the server (the server has asked for the client to provide credentials)
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: command terminated with exit code 1

根据官方文档:Using GitLab CI/CD with a Kubernetes cluster | GitLab 的说法,是因为自建的狐gitlab 未启用 https 的原因。

这就有个矛盾的地方了,如果使用自签的 https 证书,无法正常完成 kas 的搭建,不使用 https 又无法在 CI/CD workflow 中连接 k8s 集群,唯一的解决方案自有去阿里云或者腾讯云购买一个域名,然后申请1年免费的ssl证书再来尝试搭建了。

更换有效证书搭建极狐gitlab 后,job 成功运行:

...
Running on runner-5hmzywb8-project-4-concurrent-0t5n99 via gitlab-runner-gitlab-runner-7c99894b66-v6fdn...
Getting source from Git repository
00:00
Fetching changes with git depth set to 20...
Initialized empty Git repository in /builds/gitops/p1/.git/
Created fresh repository.
Checking out 044a80aa as main...
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:01
$ kubectl config get-contexts
CURRENT   NAME                   CLUSTER   AUTHINFO   NAMESPACE
          gitops/agentk:agent1   gitlab    agent:1    
$ kubectl config use-context gitops/agentk:agent1
Switched to context "gitops/agentk:agent1".
$ kubectl get pod -A
NAMESPACE                 NAME                                           READY   STATUS      RESTARTS   AGE
kube-system               helm-install-traefik-2xwdx                     0/1     Completed   0          21m
kube-system               svclb-traefik-wl6cb                            2/2     Running     0          21m
kube-system               local-path-provisioner-5ff76fc89d-sppxw        1/1     Running     0          21m
kube-system               traefik-6f9cbd9bd4-46lwd                       1/1     Running     0          21m
kube-system               metrics-server-86cbb8457f-ps94b                1/1     Running     0          21m
kube-system               coredns-854c77959c-jhq64                       1/1     Running     0          18m
default                   gitlab-runner-gitlab-runner-7c99894b66-v6fdn   1/1     Running     0          17m
gitlab-kubernetes-agent   gitlab-agent-79d47cbb87-rm9zr                  1/1     Running     0          9m53s
default                   runner-5hmzywb8-project-4-concurrent-0t5n99    2/2     Running     0          53s
Cleaning up project directory and file based variables
00:01
Job succeeded
posted @ 2022-08-11 11:22  leffss  阅读(2994)  评论(0编辑  收藏  举报