以之前构建完成的Webhook工程为例,将此Go应用部署至k8s中并指定为认证服务器

构建镜像

在工程根目录创建Dockerfile

FROM alpine:3.17
WORKDIR /app
# 复制已编译好的二进制文件(此处hook-demo为已构建的Go应用)
COPY hook-demo /app/
# 设置可执行权限
RUN chmod +x /app/hook-demo
# 暴露服务端口
EXPOSE 9999
# 运行应用
CMD ["/app/hook-demo"]

Dockerfile所在目录中,运行sudo docker build -t webhook-auth:v1.0 .

完成后检查:

ficn@master:~/k8s-webhook-auth$ sudo docker images
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
webhook-auth   v1.0      536c17b2a66c   13 seconds ago   31.8MB
alpine         3.17      775f483016a7   7 months ago     7.08MB

Pod与Service部署

创建deploy-webhook.yaml

# ~/deploy/deploy-webhook.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webhook-auth
  namespace: kube-authen  # 命名空间
  labels:
    app: webhook-auth
spec:
  replicas: 1  # 本地开发环境,使用单个副本
  selector:
    matchLabels:
      app: webhook-auth
  template:
    metadata:
      labels:
        app: webhook-auth
    spec:
      containers:
      - name: webhook-auth
        image: webhook-auth:v1.0  # 本地镜像名称
        imagePullPolicy: Never  # 强制使用本地镜像,不尝试从远程拉取
        ports:
        - containerPort: 9999  # webhook实际端口
          name: http

创建service-webhook.yaml

# ~/deploy/service-webhook.yaml
apiVersion: v1
kind: Service
metadata:
  name: webhook-auth-svc
  namespace: kube-authen  # 与Deployment使用相同的命名空间
spec:
  ports:
  - port: 9998  # 外部访问端口
    targetPort: 9999  # 指向容器的9999端口
    name: https
  selector:
    app: webhook-auth

docker镜像导入containerd

k8s在较新的版本中移除了dockershim,默认使用containerd作为容器运行时,所以想要使集群正确找到并识别容器镜像,需要将该镜像导入至containerd中

在master机,将docker镜像导出为.tar文件:

ficn@master:~/deploy$ sudo docker save > webhook-auth.tar webhook-auth

然后使用scp命令将该文件传输至工作节点:

# 提前在node上创建 ~/images 目录
ficn@master:~/deploy$ scp webhook-auth.tar [email protected]:~/images

最后在工作节点上,使用ctr导入镜像,同时指定导入的命名空间为k8s.io

# cd ~/images
node@node01:~/images$ sudo ctr -n k8s.io images import webhook-auth.tar

配置API-Server

编写webhook配置文件/etc/kubernetes/pki/webhook.json

{
  "kind": "Config",
  "apiVersion": "v1",
  "preferences": {},
  "clusters": [
    {
      "name": "webhook-authn",
      "cluster": {
        "server": "http://webhook-auth-svc.kube-authen.svc.cluster.local:9998/auth"
      }
    }
  ],
  "users": [
    {
      "name": "authn-apiserver",
      "user": {
        "token": "secret"
      }
    }
  ],
  "contexts": [
    {
      "name": "webhook",
      "context": {
        "cluster": "webhook-authn",
        "user": "authn-apiserver"
      }
    }
  ],
  "current-context": "webhook"
}

If the <cluster-ip> is an IPv4 address, an A record of the following form must exist.

  • Record Format:
    • <service>.<ns>.svc.<zone>. <ttl> IN A <cluster-ip>
  • Question Example:
    • kubernetes.default.svc.cluster.local. IN A
  • Answer Example:
    • kubernetes.default.svc.cluster.local. 4 IN A 10.3.0.1

编辑/etc/kubernetes/manifests/kube-apiserver.yaml,增加以下配置以选择Webhook认证模式:

spec:
  containers:
  - command:
  - ...
  - --authentication-token-webhook-config-file=/etc/kubernets/pki/webhook.json
  - --authentication-token-webhook-version=v1
  - ...

使用DNS形式:http://webhook-auth-svc.kube-authen.svc.cluster.local:9998/auth访问Webhook服务经常失败,暂不知具体原因,后来使用ClusterIP作为替代,暂时解决了问题

查看ClusterIP:

ficn@master:~$ kubectl get svc -n kube-authen
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
webhook-auth-svc   ClusterIP   10.244.42.186   <none>        9998/TCP   50m

由此,访问Webhook服务的URL为:http://10.244.42.186:9998/auth

参考

K8S容器运行时由docker变为containerd后的必知必会

有关Service DNS的文档