kubernetes 从入门到实践
Kubernetes 入门教程
How To Setup Jenkins On Kubernetes Cluster – Beginners Guide
官方之安装 kubeadm
Kubernetes(K8S)简介

2. k8s安装/部署

2.1. k8s部署方案

k8s的几种安装方式

1. 使用官方工具kubeadm:kubeadm是一种用于快速部署k8s集群的官方工具。它提供了一些命令行工具来帮助用户安装和配置k8s集群。
2. 使用第三方工具:除了官方工具kubeadm外,还有一些第三方工具可以帮助用户部署k8s集群,如kops、kubespray等。
3. 使用云平台的k8s服务:云平台提供了一些托管的k8s服务,如AWS的EKS、GCP的GKE、阿里云的ACK等。这些服务可以让用户快速启动和管理k8s集群。
4. 手动安装:对于有经验的用户,也可以手动安装和配置k8s集群,这需要一些专业知识和技能。

下面选用第一种方式安装

2.2. 基于kubeadm安装

安装 kubeadm

  • 系统环境:ubuntu 20.04
  • 2.2.1 安装docker-ce

    master 和node都需要执行

    sudo apt-get remove docker docker-engine docker.io
    sudo apt-get update
    sudo apt-get install apt-transport-https ca-certificates curl software-properties-common -y
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    sudo apt-get update
    sudo apt-get install docker-ce=5:20.10.12~3-0~ubuntu-$(lsb_release -cs) docker-ce-cli=5:20.10.12~3-0~ubuntu-$(lsb_release -cs) containerd.io -y
    # 验证是否安装成功
    sudo docker run hello-world
    # docker 命令免sudo
    sudo usermod -aG docker $USER
    

    2.2.2 安装cri-tools

    master 和node都需要执行

    sudo sh -c 'echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$(lsb_release -rs)/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list'
    curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_$(lsb_release -rs)/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_stable.gpg > /dev/null
    sudo apt-get update
    sudo apt-get install cri-tools=1.21.0~2 -y
    crictl --version
    

    2.2.3 安装kubeadm 以及 kubelet、kubectl

    master 和node都需要执行

    # 更新 apt 包索引并安装使用 Kubernetes apt 仓库所需要的包
    sudo apt-get update
    sudo apt-get install -y apt-transport-https ca-certificates curl
    # 下载 Google Cloud 公开签名秘钥:如果不能访问,可以参考下面的方案,采用阿里云的源
    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
    # 添加 Kubernetes apt 仓库
    echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
    # 更新 apt 包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本:
    sudo apt-get update
    sudo apt-get install -y kubelet=1.23.1-00 kubeadm=1.23.1-00 kubectl=1.23.1-00
    sudo apt-mark hold kubelet kubeadm kubectl
    # 备用方案:如果不能访问google,可以使用阿里云的源
    curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
    sudo apt-add-repository "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main"
    sudo apt-get update && sudo apt-get install -y kubelet=1.23.1-00 kubeadm=1.23.1-00 kubectl=1.23.1-00
    

    2.2.4. 安装k8s需要的镜像

    GCR_URL=k8s.gcr.io
    INNER_CR=registry.cn-hangzhou.aliyuncs.com/google_containers
    images=(kube-apiserver:v1.20.2
    kube-controller-manager:v1.20.2
    kube-scheduler:v1.20.2
    kube-proxy:v1.20.2
    pause:3.1
    etcd:3.2.24
    coredns:1.2.2)
    for imageName in ${images[@]} ; do
        echo "${imageName}"
        docker pull $INNER_CR/$imageName
        docker tag $INNER_CR/$imageName $GCR_URL/$imageName
        docker rmi $INNER_CR/$imageName
    
  • 上面镜像master都需要安装
  • TODO: node 除了kube-proxy 和 pause外,其他的都不需要安装。至于kube-proxy 和 pause是否需要,待确认
  • 2.2.5. jdk

    master 和node都需要执行

    # jenkins 依赖 jdk
    sudo apt-get install -y openjdk-11-jdk
    

    2.3. 开始使用

    2.3.1. master

    sudo service docker restart
    # 初始化,启动k8s(该命令会拉起对应的组件,比如etcd、apiserver等)
    sudo kubeadm init --pod-network-cidr=10.244.0.0/16
    # 根据提示,执行如下操作
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    # 安装网络插件:下面使用的是flannel
    curl -o kube-flannel.yml https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    kubectl apply -f kube-flannel.yml
    sudo service kubelet restart
    # 通过如下指令查看状态
    kubectl get nodes
    kubectl get pods --all-namespaces
    

    2.3.2. node

    node上只需要启动docker和kubelet即可

    sudo service docker restart
    sudo kubeadm init phase certs all
    sudo kubeadm init phase kubeconfig all
    sudo kubeadm init phase kubelet-start
    sudo service kubelet restart
    

    2.3.3 node 节点加入master

    下面只记录操作,具体实操该步骤未执行

  • 在控制节点上执行以下命令获取加入集群的TOKEN和CA证书:
  • kubeadm token create --print-join-command
    

    执行该命令后会输出kubeadm join命令,包含了加入集群的TOKEN和CA证书等必要参数。将该命令复制保存,以备后用。

  • 在要加入的节点上以root用户身份执行前一步中获取到的kubeadm join命令。例如:
  • kubeadm join <k8s-master-ip>:<k8s-master-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
    # k8s-master-ip为k8s集群控制节点的IP地址,k8s-master-port为控制节点监听的端口,默认为6443。
    
  • 等待片刻,直到节点成功加入集群。可以在控制节点上使用kubectl get nodes命令查看节点的状态。
  • 2.4. 过程中遇到的问题

  • swap分区
    k8s时,系统必须禁止掉swap分区

  • cgroup driver 问题

  • 报错:"Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: "systemd" is different from docker cgroup dri
    如果在启动Kubelet时出现"Failed to run kubelet"错误,并且错误消息中包含"failed to run Kubelet: misconfiguration: kubelet cgroup driver: "systemd" is different from docker cgroup driver",则说明您的Kubernetes和Docker在cgroup driver方面的配置不匹配

    Kubelet和Docker都需要使用相同的cgroup driver,以确保它们能够正确地管理容器和资源。默认情况下,Kubernetes使用systemd作为其cgroup driver,而Docker使用cgroupfs。如果这两个组件的cgroup driver不匹配,则无法启动Kubelet服务。
    为了解决此问题,您需要将Docker的cgroup driver更改为systemd。可以按照以下步骤完成:
    停止Docker服务:
    sudo systemctl stop docker
    修改Docker的配置文件/etc/docker/daemon.json,将"exec-opts": ["native.cgroupdriver=cgroupfs"]改为"exec-opts": ["native.cgroupdriver=systemd"]。如果该文件不存在,请创建它并添加以下内容:
      "exec-opts": ["native.cgroupdriver=systemd"]
    完成后保存并关闭文件。
    启动Docker服务:
    sudo systemctl start docker
    重新启动Kubelet服务:
    sudo systemctl restart kubelet
    完成后,Kubelet应该能够启动并正确运行了
    

    报错:networkPlugin cni failed to set up pod "example-pod_default" network: failed to delegate add: failed to set bridge addr: "cni0" already has an IP address different from 10.244.0.1/24

    ifconfig 看应该是cni的网口地址和配置不一致,可以直接删除
    sudo ip link delete cni0
    后续服务会自动创建一个正确的
    
  • node节点的配置相关
  • 报错:"command failed" err="failed to load kubelet config file, error: failed to load Kubelet config file /var/lib/kubelet/config.yaml, error failed to read kubelet config file "/var/lib/kubelet/config.yaml", error: open /var/lib/kubelet/config.yaml: no such file or directory, path: /var/lib/kubelet/config.yaml"

    sudo kubeadm init phase kubelet-start
    

    报错:open /etc/kubernetes/pki/ca.crt: no such file or directory"

    sudo kubeadm init phase certs all
    

    报错:stat /etc/kubernetes/bootstrap-kubelet.conf: no such file or directory"

    unable to load bootstrap kubeconfig

    报错:"command failed" err="failed to run Kubelet: validate service connection: validate CRI v1 runtime API for endpoint "unix:///var/run/containerd/containerd.sock": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"

    # CRI v1 runtime API is not implemented for endpoint

    3. 在master上安装jenkins

    参考上述文档即可
    https://devopscube.com/setup-jenkins-on-kubernetes-cluster/

    其中deployment.yaml有小改动,如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: jenkins
      namespace: devops-tools
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: jenkins-server
      template:
        metadata:
          labels:
            app: jenkins-server
        spec:
          securityContext:
                fsGroup: 1000
                runAsUser: 1000
          serviceAccountName: jenkins-admin
          containers:
            - name: jenkins
              image: jenkins/jenkins:lts
              resources:
                limits:
                  memory: "2Gi"
                  cpu: "1000m"
                requests:
                  memory: "500Mi"
                  cpu: "500m"
              ports:
                - name: httpport
                  containerPort: 8080
                - name: jnlpport
                  containerPort: 50000
              livenessProbe:
                httpGet:
                  path: "/login"
                  port: 8080
                initialDelaySeconds: 90
                periodSeconds: 10
                timeoutSeconds: 5
                failureThreshold: 5
              readinessProbe:
                httpGet:
                  path: "/login"
                  port: 8080
                initialDelaySeconds: 60
                periodSeconds: 10
                timeoutSeconds: 5
                failureThreshold: 3
              volumeMounts:
                - name: jenkins-data
                  mountPath: /var/jenkins_home
          tolerations:
            - key: "node-role.kubernetes.io/master"
              effect: "NoSchedule"