zoukankan      html  css  js  c++  java
  • 还不会K8S吗?先从kubeadm开始吧

    kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践。

    在Kubernetes的文档Creating a single master cluster with kubeadm中已经给出了目前kubeadm的主要特性已经处于beta状态了,在2018年将进入GA状态,说明kubeadm离可以在生产环境中使用的距离越来越近了。

    下面我将介绍一下kubeadm的安装,比起k8s的二进制安装方式,kubeadm的安装门槛较低,更容易上手。

    1. 准备工作

    1.1 机器准备

    准备三台Centos7.x虚拟机,具体配置如下:

    IP Role CPU Memory Hostname
    192.168.199.231 master >= 2C >= 2G master
    192.168.199.232 worker >= 2C >= 2G node1
    192.168.199.233 worker >= 2C >= 2G node1

    IP 根据你自己宿主机机器网段决定。

    1.2 系统配置

    1.2.1 主机名及域名解析

    # 192.168.199.231上执行
    hostnamectl set-hostname master
    
    # 192.168.199.232上执行
    hostnamectl set-hostname node1
    
    # 192.168.199.233上执行
    hostnamectl set-hostname node2
    
    # 192.168.199.231、192.168.199.232、192.168.199.233三台都执行
    cat <<EOF>>/etc/hosts
    192.168.199.231 master
    192.168.199.232 node1
    192.168.199.233 node2
    EOF
    

    设置完后,相互ping一下看看网络是否通。如:ping node1

    1.2.2 免密登录

    设置 master 可以无密码登录所有节点的 root 账户:

    ## 第一步:在master节点执行,一路回车到底
    ssh-keygen -t rsa
    
    ## 第二步:在master节点执行以下三句,然后分别输入对应机器登录密码
    ssh-copy-id root@master
    ssh-copy-id root@node1
    ssh-copy-id root@node2
    

    1.2.3 配置yum源

    注意:所有虚拟机都需要执行下面的操作

    配置阿里软件源(base和epel):

    mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak 
    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
    mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
    wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    

    最后一句记得回车,配置完过后,可通过命令:

    yum repolist

    来查看是否配置成功。如果出现如下信息则表示成功:

    • base: mirrors.aliyun.com
    • extras: mirrors.aliyun.com
    • updates: mirrors.aliyun.com

    配置国内Kubernetes源:

    cat <<EOF > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
    enabled=1
    gpgcheck=1
    repo_gpgcheck=1
    gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
    

    配置docker源:

    wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
    

    执行清理和更新:

    yum clean all && yum makecache && yum update -y	# 第一次需要比较久的时间,去喝杯水休息休息
    

    1.2.4 安装必要依赖包

    在三台机器上执行命令:

    yum install -y epel-release
    yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget
    /usr/sbin/modprobe ip_vs # 这一句记得回车
    

    ipvs 依赖 ipset

    ntp 保证各机器系统时间同步;

    1.2.5 关闭防火墙、SELinux、Swap分区

    注意:所有虚拟机都需要执行下面的操作

    关闭防火墙:

    systemctl stop firewalld && 
    systemctl disable firewalld && 
    iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && 
    iptables -P FORWARD ACCEPT
    

    关闭SELinux:

    setenforce 0
    sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
    

    关闭Swap分区:

    swapoff -a
    sed -i '/ swap / s/^(.*)$/#1/g' /etc/fstab
    

    1.2.6 配置内核参数

    注意:所有虚拟机都需要执行下面的操作

    将桥接的IPv4流量传递到iptables的链,swappiness参数调整:

    cat <<EOF >  /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward=1
    net.ipv4.tcp_tw_recycle=0
    vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
    vm.overcommit_memory=1 # 不检查物理内存是否够用
    vm.panic_on_oom=0 # 开启 OOM
    EOF
    modprobe ip_vs_rr
    modprobe br_netfilter
    sysctl --system # 记得回车
    

    2. 安装Docker

    2.1 安装

    Kubernetes从1.6开始使用CRI(Container Runtime Interface)容器运行时接口。默认的容器运行时仍然是Docker,使用的是kubelet中内置dockershim CRI实现。

    查看版本:

    # 查看docker版本
    yum list docker-ce.x86_64 --showduplicates | sort -r
    
    # 查看docker cli版本
    yum list docker-ce-cli.x86_64  --showduplicates |sort -r
    

    Kubernetes 1.15已经针对Docker的1.13.1, 17.03, 17.06, 17.09, 18.06,18.09等版本做了验证,需要注意Kubernetes 1.15最低支持的Docker版本是1.13.1。 我们这里在各节点安装docker的19.03.9版本。

    # 安装docker、docker-cli
    yum install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7
    
    # 开机启动 && 启动docker
    systemctl enable docker && systemctl start docker
    
    # 查看版本
    docker --version
    

    安装docker还可以通过脚本,详情见:https://leisure.wang/procedural-framework/docker/112.html

    2.2 配置镜像加速

    # 第一步:创建目录(不存在则创建)
    mkdir -p /etc/docker
    
    # 第二步:创建并配置daemon.json文件
    cat > /etc/docker/daemon.json <<EOF
    {
       "registry-mirrors": [
          "https://registry.docker-cn.com",
          "https://hub-mirror.c.163.com", 
          "https://docker.mirrors.ustc.edu.cn"
       ],
       "exec-opts": ["native.cgroupdriver=systemd"],
       "log-driver": "json-file",
       "log-opts": {
          "max-size": "100m",
          "max-file": "5"
       }
    }
    EOF
    
    # 第三步:重新加载配置并重启docker
    systemctl daemon-reload && systemctl restart docker
    

    确认一下iptables filter表中FOWARD链的默认策略(pllicy)为ACCEPT:

    # 命令
    iptables -nvL
    
    # 结果部分如下:
    Chain INPUT (policy ACCEPT 321 packets, 18442 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
        0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
        0     0 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
        0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0 
    

    3. 使用kubeadm部署k8s集群

    3.1 安装kubeadm、kubelet、kubectl

    需要在每台机器上都安装以下的软件包:

    • Kubelet:负责与其他节点集群通信,并进行本节点Pod和容器生命周期的管理。
    • Kubeadm:是Kubernetes的自动化部署工具,降低了部署难度,提高效率。
    • Kubectl:是Kubernetes集群管理工具。

    查看可用版本:

    yum list --showduplicates | grep 'kubeadm|kubectl|kubelet'
    

    选择安装kubeadm1.18.0、kubelet1.18.0、kubectl1.18.0

    # 安装
    yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 --disableexcludes=kubernetes
    
    # 此时还不能启动kubelet,先设置开机启动
    systemctl enable --now kubelet
    

    从安装结果可以看出还安装了cri-tools, kubernetes-cni, socat三个依赖:

    • socat是kubelet的依赖
    • cri-tools是CRI(Container Runtime Interface)容器运行时接口的命令行工具

    运行kubelet –help可以看到原来kubelet的绝大多数命令行flag参数都被DEPRECATED了。

    而官方推荐我们使用–config指定配置文件,并在配置文件中指定原来这些flag所配置的内容。具体内容可以查看这里Set Kubelet parameters via a config file。这也是Kubernetes为了支持动态Kubelet配置(Dynamic Kubelet Configuration)才这么做的,参考Reconfigure a Node’s Kubelet in a Live Cluster

    kubelet的配置文件必须是json或yaml格式,具体可查看这里

    3.2 配置kubeadm

    查看kubelet安装了哪些文件:

    # 命令
    rpm -ql kubelet
    
    # 结果
    /etc/kubernetes/manifests				# 清单目录
    /etc/sysconfig/kubelet					# 配置文件
    /usr/bin/kubelet						# 主程序
    /usr/lib/systemd/system/kubelet.service	# unit file
    

    在所有虚拟机上修改/etc/sysconfig/kubelet,加入:

    # 命令
    sed -i "s/KUBELET_EXTRA_ARGS=/KUBELET_EXTRA_ARGS="--fail-swap-on=false"/" /etc/sysconfig/kubelet
    
    # 查看是否修改
    cat /etc/sysconfig/kubelet
    
    # 查看结果
    KUBELET_EXTRA_ARGS="--fail-swap-on=false"
    

    安装 kubernetes 主要是安装它的各个镜像,而 kubeadm 已经为我们集成好了运行 kubernetes 所需的基本镜像。但由于国内的网络原因,在搭建环境时,无法拉取到这些镜像。此时我们只需要修改为阿里云提供的镜像服务即可解决该问题。

    导出配置文件(未修改文件,不可用):

    kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml
    

    针对kubeadm.yml文件做修改,新增修改处有4个,如下注释位置,做相应修改即可:

    apiVersion: kubeadm.k8s.io/v1beta2
    bootstrapTokens:
    - groups:
      - system:bootstrappers:kubeadm:default-node-token
      token: abcdef.0123456789abcdef
      ttl: 24h0m0s
      usages:
      - signing
      - authentication
    kind: InitConfiguration
    localAPIEndpoint:
      advertiseAddress: 192.168.199.231 # 修改项,更改为master节点IP
      bindPort: 6443
    nodeRegistration:
      criSocket: /var/run/dockershim.sock
      name: master
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    ---
    apiServer:
      timeoutForControlPlane: 4m0s
    apiVersion: kubeadm.k8s.io/v1beta2
    certificatesDir: /etc/kubernetes/pki
    clusterName: kubernetes
    controlPlaneEndpoint: "" # 新增项
    controllerManager: {}
    dns:
      type: CoreDNS
    etcd:
      local:
        dataDir: /var/lib/etcd
    imageRepository: registry.aliyuncs.com/google_containers # 修改项,修改为阿里云镜像仓库
    kind: ClusterConfiguration
    kubernetesVersion: v1.18.0
    networking:
      dnsDomain: cluster.local
      podSubnet: "10.244.0.0/16" # 新增项,配置Flannel的默认网段
      serviceSubnet: 10.96.0.0/12
    scheduler: {}
    ---
    # 新增项start:开启IPVS模式
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    kind: KubeProxyConfiguration
    featureGates:
      SupportIPVSProxyMode: true
    mode: ipvs
    # 新增项end:开启IPVS模式
    

    配置修改好后,将配置文件复制到node1、node2备用:

    scp kubeadm.yml root@node1:/root
    scp kubeadm.yml root@node2:/root
    

    查看和拉取镜像:

    # 查看所需镜像列表
    kubeadm config images list --config kubeadm.yml
    # 拉取镜像 (所有机器都执行)
    kubeadm config images pull --config kubeadm.yml
    # 执行完毕后,通过命令就可以看到镜像了:
    docker images
    

    3.3 使用kubeadm 配置master 节点

    注意:在master执行下面的操作

    3.3.1 安装 kubernetes 主节点

    执行以下命令初始化主节点,该命令指定了初始化时需要使用的配置文件,其中添加 --experimental-upload-certs 参数可以在后续执行加入节点时自动分发证书文件。追加的 tee kubeadm-init.log 用以输出日志。

    # 初始化命令
    kubeadm init --config=kubeadm.yml --upload-certs | tee kubeadm-init.log
    
    # 成功则返回如下信息:
    Your Kubernetes control-plane has initialized successfully!
    
    To start using your cluster, you need to run the following as a regular user:
    
      mkdir -p $HOME/.kube
      sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      sudo chown $(id -u):$(id -g) $HOME/.kube/config
    
    You should now deploy a pod network to the cluster.
    Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
      https://kubernetes.io/docs/concepts/cluster-administration/addons/
    
    Then you can join any number of worker nodes by running the following on each as root:
    
    kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef 
        --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c
    

    node1、node2想要加入集群,需要执行上一步返回结果中的命令:

    kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef 
        --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c
    

    --token:加入集群的token

    --discovery-token-ca-cert-hash:发现token证书hash

    此时还无法通过命令kubectl get nodes查看节点信息,需要等下面的配置。

    如果忘记了加入集群的命令怎么办呢?通过下面两个方法获取token和discovery-token-ca-cert-hash,然后按照上面的命令的格式拼接起来即可。

    获取Token,可以在 Master 上输入以下命令查看:

     kubeadm token list
    

    默认情况下 Token 过期是时间是24小时,如果 Token 过期以后,可以输入以下命令,生成新的 Token:

    kubeadm token create
    

    获取discovery-token-ca-cert-hash 的方法,在 Master 运行以下命令查看:

    openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
    

    注意:如果安装 kubernetes 版本和下载的镜像版本不统一则会出现 timed out waiting for the condition 错误。中途失败或是想修改配置可以使用 kubeadm reset 命令重置配置,再做初始化操作即可。

    3.3.2 配置 kubectl

    执行初始化集群时候输出结果中的命令:

    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    # 非root用户执行
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    

    验证是否成功:

    # 命令
    kubectl get nodes
    
    # 结果
    NAME     STATUS     ROLES    AGE   VERSION
    master   NotReady   master   18m   v1.18.0
    node1    NotReady   <none>   14m   v1.18.0
    node2    NotReady   <none>   14m   v1.18.0
    

    至此主机诶单配置完成。

    3.3.3 kubeadm init执行过程

    • init:指定版本进行初始化操作
    • preflight:初始化前的检查和下载所需要的 Docker 镜像文件
    • kubelet-start:生成 kubelet 的配置文件 var/lib/kubelet/config.yaml,没有这个文件 kubelet 无法启动,所以初始化之前的 kubelet 实际上启动不会成功
    • certificates:生成 Kubernetes 使用的证书,存放在 /etc/kubernetes/pki 目录中
    • kubeconfig:生成 KubeConfig 文件,存放在 /etc/kubernetes 目录中,组件之间通信需要使用对应文件
    • control-plane:使用 /etc/kubernetes/manifest 目录下的 YAML 文件,安装 Master 组件
    • etcd:使用 /etc/kubernetes/manifest/etcd.yaml 安装 Etcd 服务
    • wait-control-plane:等待 control-plan 部署的 Master 组件启动
    • apiclient:检查 Master 组件服务状态。
    • uploadconfig:更新配置
    • kubelet:使用 configMap 配置 kubelet
    • patchnode:更新 CNI 信息到 Node 上,通过注释的方式记录
    • mark-control-plane:为当前节点打标签,打了角色 Master,和不可调度标签,这样默认就不会使用 Master 节点来运行 Pod
    • bootstrap-token:生成 token 记录下来,后边使用 kubeadm join 往集群中添加节点时会用到
    • addons:安装附加组件 CoreDNS 和 kube-proxy

    3.4 使用kubeadm配置 worker 节点

    3.4.1 将worker加入到集群

    将 worker节点加入到集群中很简单,上一步也做了介绍,只需要执行init返回结果中的命令:

    kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef 
        --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c
    

    3.4.2 验证是否成功

    在master节点上运行:

    # 命令
    kubectl get cs,nodes
    
    # 结果
    NAME                                 STATUS    MESSAGE             ERROR
    componentstatus/scheduler            Healthy   ok                  
    componentstatus/controller-manager   Healthy   ok                  
    componentstatus/etcd-0               Healthy   {"health":"true"}   
    
    NAME          STATUS     ROLES    AGE   VERSION
    node/master   NotReady   master   84m   v1.18.0
    node/node1    NotReady   <none>   80m   v1.18.0
    node/node2    NotReady   <none>   79m   v1.18.0
    

    如果 worker节点加入 master 时配置有问题可以在 worker节点上使用 kubeadm reset 重置配置再使用 kubeadm join 命令重新加入即可。希望在 master 节点删除 node ,可以使用 kubeadm delete nodes 删除。

    3.4.3 查看 pod 状态

    # 在master上运行
    kubectl get pod -n kube-system -o wide
    
    # 结果
    NAME                             READY   STATUS    RESTARTS   AGE   IP                NODE     NOMINATED NODE   READINESS GATES
    coredns-7ff77c879f-k94rw         0/1     Pending   0          86m   <none>            <none>   <none>           <none>
    coredns-7ff77c879f-whhdf         0/1     Pending   0          86m   <none>            <none>   <none>           <none>
    etcd-master                      1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
    kube-apiserver-master            1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
    kube-controller-manager-master   1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
    kube-proxy-8jvj5                 1/1     Running   1          86m   192.168.199.231   master   <none>           <none>
    kube-proxy-hm8cx                 1/1     Running   1          82m   192.168.199.232   node1    <none>           <none>
    kube-proxy-psnc9                 1/1     Running   1          82m   192.168.199.233   node2    <none>           <none>
    kube-scheduler-master            1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
    

    由此可以看出 coredns 尚未运行,此时我们还需要安装网络插件。

    3.5 配置网络

    Kubernetes 中可选的 CNI 插件如下:

    • Flannel
    • Calico
    • Canal
    • Weave

    3.5.1 安装flannel网络

    # 下载kube-flannel.yml文件,如果无法下载请在附件中获取。
    curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    # 安装
    kubectl apply -f  kube-flannel.yml
    

    3.5.2 配置网卡名称(可选)

    如果Node有多个网卡的话,参考flannel issues 39701,目前需要在kube-flannel.yml中使用–iface参数指定集群主机内网网卡的名称,否则可能会出现dns无法解析。需要将kube-flannel.yml下载到本地,flanneld启动参数加上–iface=,网卡名称可通过ip address命令获取,格式为ensXX

    # 部分内容
    ......
    containers:
          - name: kube-flannel
            image: quay.io/coreos/flannel:v0.11.0-amd64
            command:
            - /opt/bin/flanneld
            args:
            - --ip-masq
            - --kube-subnet-mgr
            - --iface=ens32
    ......
    

    3.5.3 查看Pod状态

    使用kubectl get pod –all-namespaces -o wide确保所有的Pod都处于Running状态:

    # 命令
    watch kubectl get pod --all-namespaces -o wide
    # 结果(需要等待所有状态为Running,时间可能需要3-5分钟)
    NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE    IP                NODE     NOMINATED NODE   READINESS GATES
    kube-system   coredns-7ff77c879f-k94rw         1/1     Running   0          126m   10.244.0.3        master   <none>           <none>
    kube-system   coredns-7ff77c879f-whhdf         1/1     Running   0          126m   10.244.0.2        master   <none>           <none>
    kube-system   etcd-master                      1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
    kube-system   kube-apiserver-master            1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
    kube-system   kube-controller-manager-master   1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
    kube-system   kube-flannel-ds-amd64-6rcjk      1/1     Running   0          15m    192.168.199.231   master   <none>           <none>
    kube-system   kube-flannel-ds-amd64-n464m      1/1     Running   0          15m    192.168.199.232   node1    <none>           <none>
    kube-system   kube-flannel-ds-amd64-rlghv      1/1     Running   0          15m    192.168.199.233   node2    <none>           <none>
    kube-system   kube-proxy-8jvj5                 1/1     Running   1          126m   192.168.199.231   master   <none>           <none>
    kube-system   kube-proxy-hm8cx                 1/1     Running   1          122m   192.168.199.232   node1    <none>           <none>
    kube-system   kube-proxy-psnc9                 1/1     Running   1          121m   192.168.199.233   node2    <none>           <none>
    kube-system   kube-scheduler-master            1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
    

    至此基本环节已经部署完毕,如果没有问题,就可以展开k8s的学习之旅了。

    3.5.4 问题处理(可选)

    3.5.4.1 解决 ImagePullBackOff

    在使用 watch kubectl get pods --all-namespaces 命令观察 Pods 状态时如果出现 ImagePullBackOff 无法 Running 的情况,请尝试使用如下步骤处理:

    • Master 中删除 Nodes:kubectl delete nodes
    • worker中重置配置:kubeadm reset
    • worker重启计算机:reboot
    • worker重新加入集群:kubeadm join
    3.5.4.2 Master节点参与工作负载

    出于安全原因,您的群集不会在主服务器上安排pod。如果您希望能够在主服务器上安排pod,例如对于用于开发的单机Kubernetes集群,可以运行以下命令:

    # 所有主服务器都安排 pod
    kubectl taint nodes --all node-role.kubernetes.io/master-
    
    # 指定节点 master 服务器都安排 pod
    kubectl taint nodes <master-hostname> node-role.kubernetes.io/master-
    如:kubectl taint nodes master node-role.kubernetes.io/master-
    

    3.6 验证集群DNS是否可用

    3.6.1 新建文件my-nginx.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-nginx
    spec:
      selector:
        matchLabels:
          app: my-nginx
      replicas: 2
      template:
        metadata:
          labels:
            app: my-nginx
        spec:
          containers:
          - name: my-nginx
            image: nginx:1.7.9
            ports:
            - containerPort: 80
    

    3.6.2 创建Deployment并生成my-nginx服务

    # 创建Deployment
    kubectl create -f my-nginx.yaml
    
    # 查看Deployment
    kubectl get deploy
    
    # 生成服务
    kubectl expose deploy my-nginx
    
    # 查看服务
    kubectl get services(或 kubectl get svc)
    # 结果
    NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   3h2m
    my-nginx     ClusterIP   10.110.206.225   <none>        80/TCP    7m34s
    

    3.6.3 创建dnsutils-ds.yml文件

    创建另一个 Pod,查看 /etc/resolv.conf 是否包含 kubelet 配置的 --cluster-dns 和 --cluster-domain,是否能够将服务 my-nginx 解析到对应的 Cluster IP 10.110.206.225

    apiVersion: v1
    kind: Service
    metadata:
      name: dnsutils-ds
      labels:
        app: dnsutils-ds
    spec:
      type: NodePort
      selector:
        app: dnsutils-ds
      ports:
      - name: http
        port: 80
        targetPort: 80
    ---
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: dnsutils-ds
      labels:
        addonmanager.kubernetes.io/mode: Reconcile
    spec:
      selector:
        matchLabels:
          app: dnsutils-ds
      template:
        metadata:
          labels:
            app: dnsutils-ds
        spec:
          containers:
          - name: my-dnsutils
            image: tutum/dnsutils:latest
            command:
              - sleep
              - "3600"
            ports:
            - containerPort: 80
    

    3.6.4 创建pod dnsutils-ds

    kubectl create -f dnsutils-ds.yml
    

    3.6.5 查看pod节点

    # 命令
    kubectl get pods
    
    # 结果
    NAME                        READY   STATUS             RESTARTS   AGE
    curl                        0/1     CrashLoopBackOff   13         46m
    dnsutils-ds-2xgtq           1/1     Running            0          103s
    dnsutils-ds-dvzjm           1/1     Running            0          103s
    dnsutils-ds-xtsvz           1/1     Running            0          103s
    my-nginx-5c7d476867-sqpjv   1/1     Running            0          19m
    my-nginx-5c7d476867-vv57z   1/1     Running            0          19m
    

    3.6.6 开始验证DNS

    # 命令
    kubectl exec dnsutils-ds-2xgtq -- nslookup my-nginx
    
    # 结果
    Server:         10.96.0.10
    Address:        10.96.0.10#53
    
    Name:   my-nginx.default.svc.cluster.local
    Address: 10.110.206.225
    

    从结果看Address: 10.110.206.225已经成功了。

    另外,解析外部域名时,需要以 . 结尾:

    # 命令
    kubectl exec dnsutils-ds-2xgtq -- nslookup leisure.wang.
    
    # 结果
    Server:         10.96.0.10
    Address:        10.96.0.10#53
    
    Non-authoritative answer:
    Name:   leisure.wang
    Address: 121.36.158.21
    

    3.7 从集群中删除Node

    如果需要从集群中移除node2这个Node执行下面的命令:

    在master节点上执行:

    kubectl drain node2 --delete-local-data --force --ignore-daemonsets
    kubectl delete node node2
    

    在 Node 被删除,需要重启所有 kubeadm 安装状态:

    kubeadm reset
    # 如果要完全删除,请执行下面的清理命令
    ifconfig cni0 down
    ip link delete cni0
    ifconfig flannel.1 down
    ip link delete flannel.1
    rm -rf /var/lib/cni/
    

    3.8 解决apiserver访问时匿名用户禁用问题

    浏览器访问 kube-apiserver 的安全端口 6443 时,提示:

    {
    	"kind": "Status",
    	"apiVersion": "v1",
    	"metadata": {
    
    	},
    	"status": "Failure",
    	"message": "forbidden: User "system:anonymous" cannot get path "/"",
    	"reason": "Forbidden",
    	"details": {
    
    	},
    	"code": 403
    }
    

    对于正式环境,需要创建一个用户并授权,在上面二进制二进制安装里介绍过,多少还是烦了点。

    对于学习环境,我们不需要那么麻烦,不就是匿名用户被禁用了吗,直接给匿名用户授权就可以了。

    解决办法:绑定一个cluster-admin的权限

    kubectl create clusterrolebinding system:anonymous   --clusterrole=cluster-admin   --user=system:anonymous
    

    4. 部署whoami

    whoami 是一个简单的HTTP docker服务,用于打印容器ID

    在 Master 运行部署 Whoami:

    kubectl create deployment whoami --image=idoall/whoami
    

    查看 Whoami 部署状态:

    kubectl get deployments
    

    查看 Whoami 的部署信息:

    kubectl describe deployment whoami
    

    查看 Whoami 的pod信息:

    kubectl describe pod whoami
    

    为 Whoami 扩展端口;创建一个可以通过互联网访问的 Whoami 容器:

    kubectl create service nodeport whoami --tcp=80:80
    

    [本文由https://leisure.wang/整理提供]

    上面的命令将在主机上为 Whoami 部署创建面向公众的服务。
    由于这是一个节点端口部署,因此 kubernetes 会将此服务分配给32000+范围内的主机上的端口。

    查看当前的服务状态:

    # 命令
    kubectl get svc,pods -o wide
    
    # 结果
    NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE     SELECTOR
    service/dnsutils-ds   NodePort    10.97.94.13      <none>        80:30157/TCP   37m     app=dnsutils-ds
    service/kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP        3h45m   <none>
    service/my-nginx      ClusterIP   10.110.206.225   <none>        80/TCP         51m     app=my-nginx
    service/whoami        NodePort    10.108.27.255    <none>        80:32729/TCP   29s     app=whoami
    
    NAME                            READY   STATUS             RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
    pod/curl                        0/1     CrashLoopBackOff   20         82m     10.244.1.2   node1    <none>           <none>
    pod/dnsutils-ds-2xgtq           1/1     Running            0          37m     10.244.1.4   node1    <none>           <none>
    pod/dnsutils-ds-dvzjm           1/1     Running            0          37m     10.244.0.4   master   <none>           <none>
    pod/dnsutils-ds-xtsvz           1/1     Running            0          37m     10.244.2.3   node2    <none>           <none>
    pod/my-nginx-5c7d476867-sqpjv   1/1     Running            0          55m     10.244.1.3   node1    <none>           <none>
    pod/my-nginx-5c7d476867-vv57z   1/1     Running            0          55m     10.244.2.2   node2    <none>           <none>
    pod/whoami-7976c8ddf6-9lbcp     1/1     Running            0          5m13s   10.244.2.4   node2    <none>           <none>
    

    上面的服务可以看到 Whoami 运行在 32729 端口。

    测试 Whoami 服务是否运行正常:

    # 命令
    curl node1:32729 
    
    # 结果
    [mshk.top]I'm whoami-7976c8ddf6-9lbcp
    

    扩展部署应用:

    kubectl scale --replicas=3 deployment/whoami
    

    查看扩展后的结果,可以看到 Whoami 在 master、node1、node2上面都有部署

    ClusterIP 模式会提供一个集群内部的虚拟IP(与Pod不在同一网段),以供集群内部的 Pod 之间通信使用。

    删除 Whoami 部署:

    kubectl delete deployment whoami
    kubectl delete service whoami
    

    5. 部署Dashboard

    Kubernetes Dashboard 是 Kubernetes 集群的 Web UI,用于管理集群。

    5.1 安装

    注:在master节点上进行如下操作

    5.1.0 下载配置文件

    由于网络原因,可能无法下载,无法下载则请直接使用5.1.1文件内容

    wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
    

    如果下载成功,请参照5.1.1做如下修改:

    1. 修改镜像地址为阿里云
    2. 修改类型为 NodePort 访问(无type则新增)
    3. 设置端口号为 30001

    5.1.1 创建文件kubernetes-dashboard.yaml

    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard-certs
      namespace: kube-system
    type: Opaque
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kube-system
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: kubernetes-dashboard-minimal
      namespace: kube-system
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["create"]
    - apiGroups: [""]
      resources: ["configmaps"]
      verbs: ["create"]
    - apiGroups: [""]
      resources: ["secrets"]
      resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
      verbs: ["get", "update", "delete"]
    - apiGroups: [""]
      resources: ["configmaps"]
      resourceNames: ["kubernetes-dashboard-settings"]
      verbs: ["get", "update"]
    - apiGroups: [""]
      resources: ["services"]
      resourceNames: ["heapster"]
      verbs: ["proxy"]
    - apiGroups: [""]
      resources: ["services/proxy"]
      resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
      verbs: ["get"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: kubernetes-dashboard-minimal
      namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: kubernetes-dashboard
      namespace: kube-system
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kube-system
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          k8s-app: kubernetes-dashboard
      template:
        metadata:
          labels:
            k8s-app: kubernetes-dashboard
        spec:
          containers:
          - name: kubernetes-dashboard
            image: registry.aliyuncs.com/google_containers/kubernetes-dashboard-amd64:v1.10.1 # 修改镜像地址为阿里云
            ports:
            - containerPort: 8443
              protocol: TCP
            args:
              - --auto-generate-certificates
            volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs
            - mountPath: /tmp
              name: tmp-volume
            livenessProbe:
              httpGet:
                scheme: HTTPS
                path: /
                port: 8443
              initialDelaySeconds: 30
              timeoutSeconds: 30
          volumes:
          - name: kubernetes-dashboard-certs
            secret:
              secretName: kubernetes-dashboard-certs
          - name: tmp-volume
            emptyDir: {}
          serviceAccountName: kubernetes-dashboard
          tolerations:
          - key: node-role.kubernetes.io/master
            effect: NoSchedule
    ---
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kube-system
    spec:
      type: NodePort # 修改类型为 NodePort 访问(无type则新增)
      ports:
        - port: 443
          targetPort: 8443
          nodePort: 30001 # 设置端口号为 30001
      selector:
        k8s-app: kubernetes-dashboard
    

    5.1.2 部署

    kubectl create -f kubernetes-dashboard.yaml
    

    5.1.3 查看

    kubectl -n kube-system get pods
    kubectl -n kube-system get service kubernetes-dashboard
    kubectl -n kube-system describe service kubernetes-dashboard
    

    5.2 访问

    需要使用 NodeIP:30001(如:https://192.168.199.231:30001/) 访问 Dashboard,因为证书原因除火狐浏览器外其它浏览器无法直接打开页面。

    作为学习,暂时可以不用在意这些细节。访问后,在火狐里点击高级>接受风险并继续。

    此时将会看到“Kubernetes 仪表板”。

    5.3 登录

    5.3.1 kubeconfig方式

    该config文件位置一般是 ~/.kube/config(Master节点),只要将该文件下载到本地机器上,登录的时候选择它就行了。

    5.3.2 令牌方式

    创建访问Dashboard的token,需要创建一个 Admin 用户并授予 Admin 角色绑定,使用下面的 yaml文件 创建 admin 用户并赋予管理员权限,然后可以通过 Token 访问 kubernetes。

    创建 kubernetes-dashboard-admin.yaml 文件:

    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: kubernetes-dashboard
      labels:
        k8s-app: kubernetes-dashboard
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: kubernetes-dashboard
      namespace: kube-system
    

    执行部署:

    kubectl apply -f kubernetes-dashboard-admin.yaml
    

    获取secret中的token值:

    kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token
    # 记得替换成你自己的secret资源名 
    kubectl -n kube-system describe secret kubernetes-dashboard-token-bsjtr
    

    也可以通过 jsonpath 直接获取 token:

    kubectl -n kube-system get secret kubernetes-dashboard-token-bsjtr -o jsonpath={.data.token}|base64 -d
    

    也可以使用下面的命令,直接获取 kubernetes-dashboard-token 的值,然后直接打印输出:

    k8tokenvalue=`kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token | awk '{print $2}'`;kubectl -n kube-system get secret $k8tokenvalue -o jsonpath={.data.token}|base64 -d | awk '{print $1}'
    

    注意:下面的获取token值的方式和上面三种方式选择一种即可。

    您还可以通过kubectl create clusterrolebinding的方式来授予 Dashboard 服务 Admin 管理员权限:

    kubectl create serviceaccount dashboard-admin -n kube-system
    kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
    kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
    

    登录成功后就能看到后台页面了:

    6. Weave Scope 监控集群

    创建 Kubernetes 集群并部署容器化应用只是第一步。一旦集群运行起来,我们需要确保一起正常,所有必要组件就位并各司其职,有足够的资源满足应用的需求。Kubernetes 是一个复杂系统,运维团队需要有一套工具帮助他们获知集群的实时状态,并为故障排查提供及时和准确的数据支持。

    6.1 安装

    Weave Scope 是 Docker 和 Kubernetes 可视化监控工具。Scope 提供了至上而下的集群基础设施和应用的完整视图,用户可以轻松对分布式的容器化应用进行实时监控和问题诊断。

    在 K8s 集群中安装 Scope 的方法很简单,使用下面的命令:

    # 命令
    kubectl apply -f "https://cloud.weave.works/k8s/scope.yaml?k8s-version=$(kubectl version | base64 | tr -d '
    ')&k8s-service-type=NodePort"
    
    # 结果
    service-type=NodePort"
    namespace/weave created
    serviceaccount/weave-scope created
    clusterrole.rbac.authorization.k8s.io/weave-scope created
    clusterrolebinding.rbac.authorization.k8s.io/weave-scope created
    deployment.apps/weave-scope-app created
    service/weave-scope-app created
    deployment.apps/weave-scope-cluster-agent created
    daemonset.apps/weave-scope-agent created
    

    部署成功后有如下组件:

    # 命令
    kubectl get pod -n weave
    # 结果
    NAME                                         READY   STATUS              RESTARTS   AGE
    weave-scope-agent-2t7z2                      0/1     ContainerCreating   0          60s
    weave-scope-agent-ll9r9                      0/1     ContainerCreating   0          60s
    weave-scope-agent-qzp2b                      0/1     ContainerCreating   0          60s
    weave-scope-app-bc7444d59-lznk8              0/1     ContainerCreating   0          62s
    weave-scope-cluster-agent-7944c858c9-ms7mz   0/1     ContainerCreating   0          61s
    
    # 命令
    kubectl get svc -n weave
    # 结果
    NAME              TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
    weave-scope-app   NodePort   10.108.61.84   <none>        80:30286/TCP   3m9s
    
    # 命令
    kubectl get deploy -n weave
    # 结果
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    weave-scope-app             1/1     1            1           4m19s
    weave-scope-cluster-agent   1/1     1            1           4m18s
    
    • DaemonSet weave-scope-agent,集群每个节点上都会运行的 scope agent 程序,负责收集数据。
    • Deployment weave-scope-app,scope 应用,从 agent 获取数据,通过 Web UI 展示并与用户交互。
    • Service weave-scope-app,默认是 ClusterIP 类型,我们已经在上面的命令中添加了参数k8s-service-type=NodePort修改为 NodePort。

    6.2 使用Scope

    浏览器访问http://MASTER_IP:30286/(端口可在上一步查看命令中获得),cope 默认显示当前所有的 Controller(Deployment、DaemonSet 等)。

    6.2.1 拓扑结构

    Scope 会自动构建应用和集群的逻辑拓扑。比如点击顶部 Pods,会显示所有 Pod 以及 Pod 之间的依赖关系。

    点击 Hosts,会显示各个节点之间的关系,可以在 Scope 中查看资源的 CPU 和内存使用情况。

    6.2.2 在线操作

    Scope 还提供了便捷的在线操作功能,比如选中某个 Host,点击 >_ 按钮可以直接在浏览器中打开节点的命令行终端:

    点击 Deployment 的 + 可以执行 Scale Up 操作:

    可以查看 Pod 的日志:

    可以 attach、restart、stop 容器,以及直接在 Scope 中排查问题:

    6.2.3 强大的搜索功能

    Scope 支持关键字搜索和定位资源。

    还可以进行条件搜索,比如查找和定位 MEMORY > 1M 的 Containers。

    Weave Scope 界面极其友好,操作简洁流畅,更多功能留给大家去探索。

    官方文档:https://www.weave.works/docs/scope/latest/installing/#k8s

    写在最后

    通过kubeadm安装k8s集群环境的介绍就到这里了,书写安装过程难免出现不足的地方,如果出了问题,需要读者多多思考。由于国内网络的原因,文档中所需要的大部分配置文件都已经贴了出来,读者只需要根据自己的机器环境做相应的修改即可。通过kubeadm安装k8s集群环境,相对于二进制的安装方式来说,还是比较简单的,需要多多实践,才能出真知。我是东方雨倾,感谢大家的支持,谢谢!

    附件

    链接:https://pan.baidu.com/s/1qWdZ_CclTxm2ybE4h8dziA
    提取码:ruo5

    原文地址:https://leisure.wang/procedural-framework/docker/513.html

  • 相关阅读:
    【Linux高频命令专题(7)】rm
    【Linux高频命令专题(6)】mkdir
    【mongoDB运维篇①】用户管理
    【Linux高频命令专题(5)】rmdir
    【mongoDB中级篇②】索引与expain
    【mongoDB中级篇①】游标cursor
    Lua中的字符串函数库
    ngx_lua 随笔
    Nginx与Lua
    MAC 上搭建lua
  • 原文地址:https://www.cnblogs.com/itoak/p/12945944.html
Copyright © 2011-2022 走看看