• OpenYurt环境搭建(遇到的各种坑和解决办法)



    OpenYurt文档虽然写的还可以,但是还是有很多坑,比如go语言编译版本,flannel和yurt-tunnel-dns死锁无法启动的问题,配置自动修改时修改失败等。

    主节点搭建

    查看官方文档,有两种方式,一种是用已有的k8s集群作为master,一种是从零开始安装,下面介绍这两种方式

    1. 在已有的集群安装:

      根据官方文档一步步来就好,但是会有一个问题:

      官方没有说网络插件的安装,但是OpenYurt需要网络特殊配置,文档在这里:边缘Pod网络文档,这里在Flannel中增加了MAC地址保持功能,官方也没有给配置文件yaml,经过寻找找到官方给的一个GitHub地址,里面有flannel的配置,里面有一些小问题我修改了,这里也放出来。正常init集群后,创建一个文件kube-flannel-edge.yaml,把下面的复制进去,(因为官方的镜像不支持arm64,我这里自己打包了一个镜像)

      ---
      apiVersion: policy/v1beta1
      kind: PodSecurityPolicy
      metadata:
        name: psp.flannel.unprivileged
        annotations:
          seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
          seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
          apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
          apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
      spec:
        privileged: false
        volumes:
        - configMap
        - secret
        - emptyDir
        - hostPath
        allowedHostPaths:
        - pathPrefix: "/etc/cni/net.d"
        - pathPrefix: "/etc/kube-flannel"
        - pathPrefix: "/run/flannel"
        readOnlyRootFilesystem: false
        # Users and groups
        runAsUser:
          rule: RunAsAny
        supplementalGroups:
          rule: RunAsAny
        fsGroup:
          rule: RunAsAny
        # Privilege Escalation
        allowPrivilegeEscalation: false
        defaultAllowPrivilegeEscalation: false
        # Capabilities
        allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
        defaultAddCapabilities: []
        requiredDropCapabilities: []
        # Host namespaces
        hostPID: false
        hostIPC: false
        hostNetwork: true
        hostPorts:
        - min: 0
          max: 65535
        # SELinux
        seLinux:
          # SELinux is unused in CaaSP
          rule: 'RunAsAny'
      ---
      kind: ClusterRole
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: flannel
      rules:
      - apiGroups: ['extensions']
        resources: ['podsecuritypolicies']
        verbs: ['use']
        resourceNames: ['psp.flannel.unprivileged']
      - apiGroups:
        - ""
        resources:
        - pods
        verbs:
        - get
      - apiGroups:
        - ""
        resources:
        - nodes
        verbs:
        - get
        - list
        - watch
      - apiGroups:
        - ""
        resources:
        - nodes/status
        verbs:
        - patch
      ---
      kind: ClusterRoleBinding
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: flannel
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: flannel
      subjects:
      - kind: ServiceAccount
        name: flannel
        namespace: kube-system
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: flannel
        namespace: kube-system
      ---
      kind: ConfigMap
      apiVersion: v1
      metadata:
        name: kube-flannel-cfg
        namespace: kube-system
        labels:
          tier: node
          app: flannel
      data:
        cni-conf.json: |
          {
            "name": "cbr0",
            "cniVersion": "0.3.1",
            "plugins": [
              {
                "type": "flannel",
                "delegate": {
                  "hairpinMode": true,
                  "isDefaultGateway": true
                }
              },
              {
                "type": "portmap",
                "capabilities": {
                  "portMappings": true
                }
              }
            ]
          }
        net-conf.json: |
          {
            "Network": "10.244.0.0/16",
            "Backend": {
              "Type": "vxlan"
            }
          }
      ---
      apiVersion: apps/v1
      kind: DaemonSet
      metadata:
        name: kube-flannel-ds
        namespace: kube-system
        labels:
          tier: node
          app: flannel
      spec:
        selector:
          matchLabels:
            app: flannel
        template:
          metadata:
            labels:
              tier: node
              app: flannel
          spec:
            affinity:
              nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  nodeSelectorTerms:
                  - matchExpressions:
                    - key: kubernetes.io/os
                      operator: In
                      values:
                      - linux
            hostNetwork: true
            priorityClassName: system-node-critical
            tolerations:
            - operator: Exists
              effect: NoSchedule
            serviceAccountName: flannel
            initContainers:
            - name: install-cni
              image: ccjjxx99/flannel:v0.14.0-1
              command:
              - cp
              args:
              - -f
              - /etc/kube-flannel/cni-conf.json
              - /etc/cni/net.d/10-flannel.conflist
              volumeMounts:
              - name: cni
                mountPath: /etc/cni/net.d
              - name: flannel-cfg
                mountPath: /etc/kube-flannel/
            containers:
            - name: kube-flannel
              image: ccjjxx99/flannel:v0.14.0-1
              command:
              - /opt/bin/flanneld
              args:
              - --ip-masq
              - --kube-subnet-mgr
              resources:
                requests:
                  cpu: "100m"
                  memory: "50Mi"
                limits:
                  cpu: "100m"
                  memory: "50Mi"
              securityContext:
                privileged: false
                capabilities:
                  add: ["NET_ADMIN", "NET_RAW"]
              env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: POD_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              volumeMounts:
              - name: run
                mountPath: /run/flannel
              - name: flannel-cfg
                mountPath: /etc/kube-flannel/
            volumes:
            - name: run
              hostPath:
                path: /run/flannel
            - name: cni
              hostPath:
                path: /etc/cni/net.d
            - name: flannel-cfg
              configMap:
                name: kube-flannel-cfg
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125
      • 126
      • 127
      • 128
      • 129
      • 130
      • 131
      • 132
      • 133
      • 134
      • 135
      • 136
      • 137
      • 138
      • 139
      • 140
      • 141
      • 142
      • 143
      • 144
      • 145
      • 146
      • 147
      • 148
      • 149
      • 150
      • 151
      • 152
      • 153
      • 154
      • 155
      • 156
      • 157
      • 158
      • 159
      • 160
      • 161
      • 162
      • 163
      • 164
      • 165
      • 166
      • 167
      • 168
      • 169
      • 170
      • 171
      • 172
      • 173
      • 174
      • 175
      • 176
      • 177
      • 178
      • 179
      • 180
      • 181
      • 182
      • 183
      • 184
      • 185
      • 186
      • 187
      • 188
      • 189
      • 190
      • 191
      • 192
      • 193
      • 194
      • 195
      • 196
      • 197
      • 198
      • 199
      • 200
      • 201
      • 202
      • 203
      • 204
      • 205
      • 206
      • 207
      • 208
      • 209
      • 210
      • 211
      • 212
      • 213
      • 214
      • 215
      • 216
      • 217
      • 218
      • 219
      • 220
      • 221
      • 222
      • 223
      • 224

      然后

      kubectl apply -f kube-flannel-edge.yaml
      
      • 1

      剩下的内容按官方文档一步一步走就好了。

    2. 从零开始安装

      还是看官方文档:OpenYurt从零开始安装官方文档,下面介绍这种方法。但还是建议用第一种。。。因为这个yurtadm init命令已经很久没人维护了,bug很多。

    编译 yurtadm

    系统需要安装了 git, golang 1.16(官方写的1.13+,但是实测不行,必须1.16以上,1.19太新也不行,我用的就是1.16才能不出bug)

    执行以下命令来完成安装:

    git clone https://github.com/openyurtio/openyurt.git
    cd openyurt
    make build WHAT="yurtadm" ARCH="amd64" REGION=cn
    
    • 1
    • 2
    • 3

    可执行文件 yurtadm 将存放在_output/local/bin/linux/amd64/ 目录下。可以将 yurtadm 命令放到系统环境变量中,便于后续使用:

    cp _output/local/bin/linux/amd64/yurtadm /usr/local/bin/
    
    • 1

    yurtadm init

    yurtadm init 可以初始化一个 latest 版本 的 openyurt 集群 (目前使用的 kubernetes 版本是1.22.8)。

    例子:

    yurtadm init --apiserver-advertise-address=192.168.31.209 --yurt-tunnel-server-address=192.168.31.209 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12
    
    • 1

    这里又会有好几个坑

    安装sealer

    首先sealer可能下载不下来(如果服务器网络可以访问GitHub也许就没这个问题),需要自己去Sealer的官方GitHub用它给的命令:

    wget https://github.com/sealerio/sealer/releases/download/v0.8.6/sealer-v0.8.6-linux-amd64.tar.gz && \
    tar zxvf sealer-v0.8.6-linux-amd64.tar.gz && mv sealer /usr/bin
    
    • 1
    • 2

    因为网络原因,也可以用自己的电脑下载然后传到服务器上解压到/usr/bin就好了

    自己修改配置

    运行完之后,还有更大的坑,最后说的是成功了,enjoy it,但是看上面的日志,根本没成功:
    日志
    红框上面的一步是调整kube-apiserver,然后等待重启,结果这里调整以后,还正在重启的时候,它就说已经重启成功了,然后就开始执行下面的命令,但其实没重启成功,kubectl命令就是炸的,因此下面的命令全都会报错6443端口refused,也就是说下面这些命令根本没执行。但这里集群确实部署好了,就是一些调整的操作没有成功,所以我们要看第一种方法的文档:在已有集群安装,根据文档调整我们的设置。

    但是这之前要确定flannel和yurt-tunnel-dns的状态是不是都running了,如果都是running再进行下面的操作。
    我有一次出现他们两个死锁,flannel在等待dns响应,而dns又因为flannel没有给它分配ip也启动不起来,这个问题一种解决的思路是回到文档上一步,把上一步中apiserver的DNS修改全都回退,flannel就能成功布置了,然后再布置yurt-tunnel-dns,就可以获取到flannel给的ip了。但是这个方法有点麻烦。
    我直接yurtadm reset然后重新init,第二次就没这个问题了,很玄学。

    因为上面红框里的日志是coreDNS这里就失败了,所以要从官方文档的 2.4 Addons调整 开始自己调

    coreDNS调整

    首先就是调整coreDNS,按文档说的来:

    CoreDNS 支持服务流量拓扑
    kubectl annotate svc kube-dns -n kube-system openyurt.io/topologyKeys='openyurt.io/nodepool'
    
    • 1
    CoreDNS DaemonSet部署

    把它给的配置文件内容复制下来,自己写一个coredns.yaml,注意修改里面image: registry.aliyuncs.com/google_containers/coredns:1.7.0这一行的版本号,我用的是1.8.4。如下:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      labels:
        k8s-app: kube-dns
      name: coredns
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          k8s-app: kube-dns
      template:
        metadata:
          labels:
            k8s-app: kube-dns
        spec:
          containers:
          - args:
            - -conf
            - /etc/coredns/Corefile
            image: registry.aliyuncs.com/google_containers/coredns:1.8.4
            livenessProbe:
              failureThreshold: 5
              httpGet:
                path: /health
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 60
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 5
            name: coredns
            ports:
            - containerPort: 53
              name: dns
              protocol: UDP
            - containerPort: 53
              name: dns-tcp
              protocol: TCP
            - containerPort: 9153
              name: metrics
              protocol: TCP
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /ready
                port: 8181
                scheme: HTTP
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 1
            resources:
              limits:
                memory: 170Mi
              requests:
                cpu: 100m
                memory: 70Mi
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                add:
                - NET_BIND_SERVICE
                drop:
                - all
              readOnlyRootFilesystem: true
            volumeMounts:
            - mountPath: /etc/coredns
              name: config-volume
              readOnly: true
          dnsPolicy: Default
          nodeSelector:
            kubernetes.io/os: linux
          priorityClassName: system-cluster-critical
          serviceAccount: coredns
          serviceAccountName: coredns
          tolerations:
          - operator: Exists
          - key: CriticalAddonsOnly
            operator: Exists
          - effect: NoSchedule
            key: node-role.kubernetes.io/master
          volumes:
          - configMap:
              defaultMode: 420
              items:
              - key: Corefile
                path: Corefile
              name: coredns
            name: config-volume
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    然后

    kubectl apply -f coredns.yaml
    
    • 1

    因为用daemonset部署了,就不需要deployment部署了,所以把deployment的副本数改成0:

    kubectl scale --replicas=0 deployment/coredns -n kube-system
    
    • 1
    KubeProxy调整

    按照官方文档

    kubectl edit cm -n kube-system kube-proxy
    
    • 1

    注释掉clientConnection.kubeconfig,修改完后效果如下:

    apiVersion: v1
    data:
      config.conf: |-
        apiVersion: kubeproxy.config.k8s.io/v1alpha1
        bindAddress: 0.0.0.0
        bindAddressHardFail: false
        clientConnection:
          acceptContentTypes: ""
          burst: 0
          contentType: ""
          # kubeconfig: /var/lib/kube-proxy/kubeconfig.conf <-- 删除这个配置
          qps: 0
        clusterCIDR: 100.64.0.0/10
        configSyncPeriod: 0s
    // 省略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    部署OpenYurt的Control-Plane组件

    去掉污点

    这一步又有一个大坑,主节点现在用kubectl get node命令来看是ready的,但是污点不知道为什么没有删除,还是有一个notready的污点,会导致什么pod都部署不上去,describe pod的时候日志是这样的:

    Warning  FailedScheduling  42s (x2 over 110s)  default-scheduler  0/1 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate.
    
    • 1

    因此要先运行下面的,去掉主节点的污点

    kubectl taint node master2015 node.kubernetes.io/not-ready-
    
    • 1

    然后再按照文档安装yurt-app-manager

    部署openyurt/yurt-app-manager组件

    克隆下来yurt-app-manager仓库,进入里面,运行:

    helm install yurt-app-manager -n kube-system ./charts/yurt-app-manager/
    
    • 1

    应该不会有问题,确认yurt-app-manager组件的pod和service配置已经成功创建:

    kubectl get pod -n kube-system | grep yurt-app-manager
    kubectl get svc -n kube-system | grep yurt-app-manager
    
    • 1
    • 2

    创建节点池:

    cat <
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    节点加入节点池:

    kubectl label node master2015 apps.openyurt.io/desired-nodepool=master
    
    • 1
    部署openyurt/openyurt组件

    克隆下来openyurt的仓库(刚刚编译yurtadm的时候已经克隆了,进去)

    helm install openyurt -n kube-system ./charts/openyurt/
    
    • 1

    确认是否安装成功:

    helm list -A
    
    • 1

    部署成功:

    部署成功

    调整kube-proxy镜像位置:

    因为yurtadm是调用sealer安装的集群,sealer把各种镜像下载好后,都存在本地的sea.hub:5000这样一个仓库,在其他节点是无法访问的,所以如果子节点要加入,就会找不到镜像,所以要把这个镜像换成官方的镜像:

    kubectl edit ds kube-proxy -n kube-system
    
    • 1

    在40行左右找到image,把镜像改成:

    registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.22.8
    
    • 1

    效果

    子节点加入

    先在主节点查看token

    keadm token list
    
    • 1

    复制过期时间还有23小时的那个token

    子节点也要提前编译好yurtadm,如果主节点和子节点架构一样的话(比如都是amd64),那就可以直接把主节点的复制过来,然后给运行权限:

    chmod 777 /usr/local/bin/yurtadm
    
    • 1

    然后用join命令加入

    yurtadm join 192.168.31.209:6443 --token=t6qejp.7euqu5t5d0c9camq --node-type=edge --discovery-token-unsafe-skip-ca-verification --v=5
    
    • 1

    这里还会有坑,比如一直卡在 waiting hub agent ready。可能是因为kubelet根本没启动,可以再开一个ssh窗口查看kubelet的日志:

    journalctl -u kubelet -xe
    
    • 1

    我第一次失败的原因是Docker中Cgroup Driver的问题,因为yurtadm创建的kubelet的默认驱动为systemd,而我的docker是cgroupfs,所以无法启动。
    解决方法是修改/etc/docker/daemon.json,如果没有就创建新的,配置里面添加:

    {
      "exec-opts": [
        "native.cgroupdriver=systemd"
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    重启docker

    systemctl daemon-reload
    systemctl restart docker
    
    • 1
    • 2

    然后

    yurtadm reset
    
    • 1

    然后再运行join命令,应该就能成功。

    但是最后我的集群还是有问题,因为我的边缘节点是arm64架构的,但是openyurt官方的集群里修改过的flannel只有amd64架构的镜像,所以我的子节点无法运行flannel,解决方法是:

    1. 如果动手能力强可以自己编译镜像,如果想用现成的直接看2

      按照边缘Pod网络文档的说明自己编译一个arm64的镜像:

      先按照边缘Pod网络的文档打补丁后,再按照flannel的文档使用命令ARCH=arm64 make image就可以打包了。可能会提示一个“qemu-aarch64-static”找不到的问题,我发现只要把dist文件夹里的qemu-arm64-static复制一份改名叫qemu-aarch64-static就可以成功生成镜像,并且在我的arm64的机器上可以成功运行。
      最后把生成的文件传到arm64的节点上,加载到docker

      docker load --input flanneld-v0.14.0-1-g1e376862-arm64.docker
      
      • 1

      然后把镜像改名为官方原本在yaml里写的名字,过一会儿就可以成功部署flannel的pod了

      docker tag quay.io/coreos/flannel:v0.14.0-1-g1e376862-arm64 registry.cn-hangzhou.aliyuncs.com/openyurt/flannel-edge:v0.14.0-1
      
      • 1
    2. 我已经编译了arm64和amd64双架构的镜像,可以更改flannel配置中的镜像为我的镜像:

      kubectl edit ds kube-flannel-ds -n kube-system
      
      • 1

      进去之后在57行和89行左右把镜像名称改为:

      ccjjxx99/flannel:v0.14.0-1
      
      • 1

      然后它会自动去dockerhub拉取我上传的镜像,会根据架构自己拉取适合的。

      我也在GitHub提issue了,希望以后会官方会提供arm64的镜像。

    部署成功

    最后运行

    kubectl get nodes
    
    • 1
    kubectl get pods -n kube-system
    
    • 1

    可以看到全部部署成功
    成功
    成功

  • 相关阅读:
    C++封闭类
    QT+OSG/osgEarth编译之二十五:GeoTIFF+Qt编译(一套代码、一套框架,跨平台编译,版本:GeoTIFF-2.12.1)
    JavaScript中数组方法总结(全)
    [附源码]java毕业设计文章管理系统查重PPT
    Java NIO与IO的区别和比较
    随想006:帮忙的时机
    Spring框架(七):Spring的Web配置应用
    kafka安装
    补码 符号数的二进制 整数
    【c++刷题Day3】专题3T2
  • 原文地址:https://blog.csdn.net/weixin_43168190/article/details/127774243