K8S 1.10 手动安装-环境准备

2018/05/07 k8s

环境介绍

软件版本

  • Kubernetes v1.10.0
  • CNI v0.6.0
  • Etcd v3.1.13
  • Calico V3.0.4
  • Docker CE lastest version
IP Address Hostname CPU Memory
10.20.40.115 k8s-m1 2 2GB
10.20.40.113 k8s-m2 2 2GB
10.20.40.116 k8s-m3 2 2GB
10.20.40.121 k8s-n1 2 2GB
10.20.40.106 k8s-n2 2 2GB
10.20.40.119 k8s-n3 2 2GB

另外所以master节点提供一组VIP 10.20.40.10

m主要为控制节点,n为工作节点 所有操作以root用户执行

环境准备

  • 所有节点网络互通,k8s-m1 ssh免密码登录其他节点
  • 所有防火墙SELinux 关闭,如CentOS:

      $ systemctl stop firewalld && systemctl disable firewalld
      $ setenforce 0
      $ sed -i 's/enforcing/disabled/g' /etc/selinux/config
    
  • 所有节点需要设定/etc/hosts解析到所有主机:

      10.20.40.115 k8s-m1
      10.20.40.113 k8s-m2
      10.20.40.116 k8s-m3
      10.20.40.121 k8s-n1
      10.20.40.106 k8s-n2
      10.20.40.119 k8s-n3
    
  • 所有节点都需要安装Docker CE版本容器引擎:

      $ curl -fsSL "https://get.docker.com/" | sh
    

不管是UbuntuCentOS都只需执行该命令就会自动安装最新版本Docker。 CentOS 安装完成后,执行以下命令启动: $ systemctl enable docker && systemctl start docker

  • 所有节点需要设置/etc/sysctl.d/k8s.conf的系统参数:

      $ cat <<EOF > /etc/sysctl.d/k8s.conf
      net.ipv4.ip_forward = 1
      net.bridge.bridge-nf-call-ip6tables = 1
      net.bridge.bridge-nf-call-iptables = 1
      EOF
    
      $ sysctl -p /etc/sysctl.d/k8s.conf
    
  • Kubernetes v1.8+ 要去关闭系统Swap,如果不关闭需要修改kubelet设定参数,再所有节点利用以下命令关闭:

      $ swapoff -a && sysctl -w vm.swappiness=0   > `/etc/fstab`也要注释掉`SWAP`挂载
    
  • 下载Kubernetes 二进制文件

      export KUBE_URL="https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/amd64"
      wget "${KUBE_URL}/kubelet" -O /usr/local/bin/kubelet
      chmod +x /usr/local/bin/kubelet
    
  • node节点 忽略下载kubectl

      wget "${KUBE_URL}/kubectl" -O /usr/local/bin/kubectl
      chmod +x /usr/local/bin/kubectl
    
  • 下载Kubernetes CNI 二进制文件

      mkdir -p /opt/cni/bin && cd /opt/cni/bin
      export CNI_URL="https://github.com/containernetworking/plugins/releases/download"
      wget -qO- --show-progress "${CNI_URL}/v0.6.0/cni-plugins-amd64-v0.6.0.tgz" | tar -zx
    
  • 在k8s-m1需要安装CFSSL工具,这将会用来建立 TLS Certificates。

      export CFSSL_URL="https://pkg.cfssl.org/R1.2"
      wget "${CFSSL_URL}/cfssl_linux-amd64" -O /usr/local/bin/cfssl
      wget "${CFSSL_URL}/cfssljson_linux-amd64" -O /usr/local/bin/cfssljson
      chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson
    

建立集群 CA keys 与 Certificates

在这个部分,将需要产生多个元件的 Certificates,这包含 Etcd、Kubernetes 元件等,并且每个集群都会有一个根数位凭证认证机构(Root Certificate Authority)被用在认证 API Server 与 Kubelet 端的凭证。

P.S. 这边要注意 CA JSON 档的CN(Common Name)与O(Organization)等内容是会影响 Kubernetes 元件认证的。

Etcd

首先在k8s-m1建立/etc/etcd/ssl资料夹,然后进入目录完成以下操作。

mkdir -p /etc/etcd/ssl && cd /etc/etcd/ssl
export PKI_URL="https://kairen.github.io/files/manual-v1.10/pki"

下载ca-config.json与etcd-ca-csr.json文件,并从 CSR json 产生 CA keys 与 Certificate:

wget "${PKI_URL}/ca-config.json" "${PKI_URL}/etcd-ca-csr.json"

cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare etcd-ca

下载etcd-csr.json文件,并产生 Etcd 证书:

wget "${PKI_URL}/etcd-csr.json"
# -hostname需修改成所有 masters 节点。
cfssl gencert \
    -ca=etcd-ca.pem \
    -ca-key=etcd-ca-key.pem \
    -config=ca-config.json \
    -hostname=127.0.0.1,10.20.40.113,10.20.40.114,10.20.40.115 \
    -profile=kubernetes \
    etcd-csr.json | cfssljson -bare etcd

完成后删除不必要文件:

rm -rf *.json *.csr

确认/etc/etcd/ssl有以下文件:

ls /etc/etcd/ssl

etcd-ca-key.pem  etcd-ca.pem  etcd-key.pem  etcd.pem

复制相关文件至其他 Etcd 节点,这边为所有master节点:

for NODE in k8s-m2 k8s-m3; do
    echo "--- $NODE ---"
    ssh ${NODE} "mkdir -p /etc/etcd/ssl"
    for FILE in etcd-ca-key.pem  etcd-ca.pem  etcd-key.pem  etcd.pem; do
      scp /etc/etcd/ssl/${FILE} ${NODE}:/etc/etcd/ssl/${FILE}
    done
done

Kubernetes

在k8s-m1建立pki资料夹,然后进入目录完成以下章节操作。

mkdir -p /etc/kubernetes/pki && cd /etc/kubernetes/pki
export PKI_URL="https://kairen.github.io/files/manual-v1.10/pki"
export KUBE_APISERVER="https://10.20.40.88:6443"

下载ca-config.json与ca-csr.json文件,并产生 CA 金钥:

wget "${PKI_URL}/ca-config.json" "${PKI_URL}/ca-csr.json"
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls ca*.pem

ca-key.pem  ca.pem

API Server Certificate

下载apiserver-csr.json文件,并产生 kube-apiserver 凭证:

wget "${PKI_URL}/apiserver-csr.json"

cfssl gencert \
    -ca=ca.pem \
    -ca-key=ca-key.pem \
    -config=ca-config.json \
    -hostname=10.96.0.1,10.20.40.88,127.0.0.1,kubernetes.default \
    -profile=kubernetes \
    apiserver-csr.json | cfssljson -bare apiserver

ls apiserver*.pem
apiserver-key.pem  apiserver.pem
  • 这边-hostname的96.0.1是 Cluster IP 的 Kubernetes 端点;
  • 16.35.10为虚拟 IP 位址(VIP);
  • default为 Kubernetes DN。

Front Proxy Certificate

下载front-proxy-ca-csr.json文件,并产生 Front Proxy CA 金钥,Front Proxy 主要是用在 API aggregator 上:

wget "${PKI_URL}/front-proxy-ca-csr.json"
cfssl gencert \
    -initca front-proxy-ca-csr.json | cfssljson -bare front-proxy-ca

ls front-proxy-ca*.pem
front-proxy-ca-key.pem  front-proxy-ca.pem

下载front-proxy-client-csr.json文件,并产生 front-proxy-client 证书:

wget "${PKI_URL}/front-proxy-client-csr.json"

cfssl gencert \
    -ca=front-proxy-ca.pem \
    -ca-key=front-proxy-ca-key.pem \
    -config=ca-config.json \
    -profile=kubernetes \
    front-proxy-client-csr.json | cfssljson -bare front-proxy-client

ls front-proxy-client*.pem

front-proxy-client-key.pem  front-proxy-client.pem

Admin Certificate

下载admin-csr.json文件,并产生 admin certificate 凭证:

wget "${PKI_URL}/admin-csr.json"

cfssl gencert \
    -ca=ca.pem \
    -ca-key=ca-key.pem \
    -config=ca-config.json \
    -profile=kubernetes \
    admin-csr.json | cfssljson -bare admin

ls admin*.pem
admin-key.pem  admin.pem

接着通过以下指令产生名称为 admin.conf 的 kubeconfig 档:

# admin set cluster
kubectl config set-cluster kubernetes \
    --certificate-authority=ca.pem \
    --embed-certs=true \
    --server=${KUBE_APISERVER} \
    --kubeconfig=../admin.conf

# admin set credentials
kubectl config set-credentials kubernetes-admin \
    --client-certificate=admin.pem \
    --client-key=admin-key.pem \
    --embed-certs=true \
    --kubeconfig=../admin.conf

# admin set context
kubectl config set-context kubernetes-admin@kubernetes \
    --cluster=kubernetes \
    --user=kubernetes-admin \
    --kubeconfig=../admin.conf

# admin set default context
kubectl config use-context kubernetes-admin@kubernetes \
    --kubeconfig=../admin.conf

Controller Manager Certificate

下载manager-csr.json文件,并产生 kube-controller-manager certificate 凭证:

wget "${PKI_URL}/manager-csr.json"

cfssl gencert \
    -ca=ca.pem \
    -ca-key=ca-key.pem \
    -config=ca-config.json \
    -profile=kubernetes \
    manager-csr.json | cfssljson -bare controller-manager

ls controller-manager*.pem
controller-manager-key.pem  controller-manager.pem

若节点 IP 不同,需要修改manager-csr.json的hosts。

接着通过以下指令产生名称为controller-manager.conf的 kubeconfig 档:

# controller-manager set cluster
kubectl config set-cluster kubernetes \
    --certificate-authority=ca.pem \
    --embed-certs=true \
    --server=${KUBE_APISERVER} \
    --kubeconfig=../controller-manager.conf

# controller-manager set credentials

kubectl config set-credentials system:kube-controller-manager \
    --client-certificate=controller-manager.pem \
    --client-key=controller-manager-key.pem \
    --embed-certs=true \
    --kubeconfig=../controller-manager.conf

# controller-manager set context

kubectl config set-context system:kube-controller-manager@kubernetes \
    --cluster=kubernetes \
    --user=system:kube-controller-manager \
    --kubeconfig=../controller-manager.conf

# controller-manager set default context

kubectl config use-context system:kube-controller-manager@kubernetes \
    --kubeconfig=../controller-manager.conf

Scheduler Certificate

下载scheduler-csr.json文件,并产生 kube-scheduler certificate 凭证:

wget "${PKI_URL}/scheduler-csr.json"

cfssl gencert \
    -ca=ca.pem \
    -ca-key=ca-key.pem \
    -config=ca-config.json \
    -profile=kubernetes \
    scheduler-csr.json | cfssljson -bare scheduler

ls scheduler*.pem
scheduler-key.pem  scheduler.pem

若节点 IP 不同,需要修改scheduler-csr.json的hosts。

接着通过以下指令产生名称为 scheduler.conf 的 kubeconfig 档:

# scheduler set cluster

kubectl config set-cluster kubernetes \
    --certificate-authority=ca.pem \
    --embed-certs=true \
    --server=${KUBE_APISERVER} \
    --kubeconfig=../scheduler.conf

# scheduler set credentials

kubectl config set-credentials system:kube-scheduler \
    --client-certificate=scheduler.pem \
    --client-key=scheduler-key.pem \
    --embed-certs=true \
    --kubeconfig=../scheduler.conf

# scheduler set context

kubectl config set-context system:kube-scheduler@kubernetes \
    --cluster=kubernetes \
    --user=system:kube-scheduler \
    --kubeconfig=../scheduler.conf

# scheduler use default context

kubectl config use-context system:kube-scheduler@kubernetes \
    --kubeconfig=../scheduler.conf

Master Kubelet Certificate

接着在所有k8s-m1节点下载kubelet-csr.json文件,并产生凭证:

wget "${PKI_URL}/kubelet-csr.json"

for NODE in k8s-m1 k8s-m2 k8s-m3; do
    echo "--- $NODE ---"
    cp kubelet-csr.json kubelet-$NODE-csr.json;
    sed -i "s/\$NODE/$NODE/g" kubelet-$NODE-csr.json;
    cfssl gencert \
      -ca=ca.pem \
      -ca-key=ca-key.pem \
      -config=ca-config.json \
      -hostname=$NODE \
      -profile=kubernetes \
      kubelet-$NODE-csr.json | cfssljson -bare kubelet-$NODE
done

ls kubelet*.pem

kubelet-k8s-m1-key.pem  kubelet-k8s-m1.pem  kubelet-k8s-m2-key.pem  kubelet-k8s-m2.pem  kubelet-k8s-m3-key.pem  kubelet-k8s-m3.pem

这边需要依据节点修改-hostname与$NODE。

完成后复制 kubelet 凭证至其他master节点:

for NODE in k8s-m2 k8s-m3; do
    echo "--- $NODE ---"
    ssh ${NODE} "mkdir -p /etc/kubernetes/pki"
    for FILE in kubelet-$NODE-key.pem kubelet-$NODE.pem ca.pem; do
      scp /etc/kubernetes/pki/${FILE} ${NODE}:/etc/kubernetes/pki/${FILE}
    done
done

接着执行以下指令产生名称为kubelet.conf的 kubeconfig 档:

for NODE in k8s-m1 k8s-m2 k8s-m3; do
    echo "--- $NODE ---"
    ssh ${NODE} "cd /etc/kubernetes/pki && \
      kubectl config set-cluster kubernetes \
        --certificate-authority=ca.pem \
        --embed-certs=true \
        --server=${KUBE_APISERVER} \
        --kubeconfig=../kubelet.conf && \
      kubectl config set-cluster kubernetes \
        --certificate-authority=ca.pem \
        --embed-certs=true \
        --server=${KUBE_APISERVER} \
        --kubeconfig=../kubelet.conf && \
      kubectl config set-credentials system:node:${NODE} \
        --client-certificate=kubelet-${NODE}.pem \
        --client-key=kubelet-${NODE}-key.pem \
        --embed-certs=true \
        --kubeconfig=../kubelet.conf && \
      kubectl config set-context system:node:${NODE}@kubernetes \
        --cluster=kubernetes \
        --user=system:node:${NODE} \
        --kubeconfig=../kubelet.conf && \
      kubectl config use-context system:node:${NODE}@kubernetes \
        --kubeconfig=../kubelet.conf && \
      rm kubelet-${NODE}.pem kubelet-${NODE}-key.pem"
done

Service Account Key

Service account 不是通过 CA 进行认证,因此不要通过 CA 来做 Service account key 的检查,这边建立一组 Private 与 Public 金钥提供给 Service account key 使用:

openssl genrsa -out sa.key 2048

openssl rsa -in sa.key -pubout -out sa.pub

ls sa.*
sa.key  sa.pub

删除不必要文件

所有信息准备完成后,就可以将一些不必要文件删除:

rm -rf *.json *.csr scheduler*.pem controller-manager*.pem admin*.pem kubelet*.pem

复制文件至其他节点

复制凭证文件至其他master节点:

for NODE in k8s-m2 k8s-m3; do
    echo "--- $NODE ---"
    for FILE in $(ls /etc/kubernetes/pki/); do
        scp /etc/kubernetes/pki/${FILE} ${NODE}:/etc/kubernetes/pki/${FILE}
    done
done

复制 Kubernetes config 文件至其他master节点:

for NODE in k8s-m2 k8s-m3; do
    echo "--- $NODE ---"
    for FILE in admin.conf controller-manager.conf scheduler.conf; do
      scp /etc/kubernetes/${FILE} ${NODE}:/etc/kubernetes/${FILE}
    done
done

Kubernetes Masters

本部分将说明如何建立与设定 Kubernetes Master 角色,过程中会部署以下元件:

  • kube-apiserver:提供 REST APIs,包含授权、认证与状态储存等。
  • kube-controller-manager:负责维护集群的状态,如自动扩展,滚动更新等。
  • kube-scheduler:负责资源排程,依据预定的排程策略将 Pod 分配到对应节点上。
  • Etcd:储存集群所有状态的 Key/Value 储存系统。
  • HAProxy:提供负载平衡器。
  • Keepalived:提供虚拟网络位址(VIP)。

部署与设定

首先在所有 master 节点下载部署元件的 YAML 文件,这边不采用二进制执行档与 Systemd 来管理这些元件,全部采用 Static Pod 来达成。这边将文件下载至/etc/kubernetes/manifests目录:

export CORE_URL="https://kairen.github.io/files/manual-v1.10/master"

mkdir -p /etc/kubernetes/manifests && cd /etc/kubernetes/manifests

for FILE in kube-apiserver kube-controller-manager kube-scheduler haproxy keepalived etcd etcd.config; do
    wget "${CORE_URL}/${FILE}.yml.conf" -O ${FILE}.yml
    if [ ${FILE} == "etcd.config" ]; then
      mv etcd.config.yml /etc/etcd/etcd.config.yml
      sed -i "s/\${HOSTNAME}/${HOSTNAME}/g" /etc/etcd/etcd.config.yml
      sed -i "s/\${PUBLIC_IP}/$(hostname -i)/g" /etc/etcd/etcd.config.yml
    fi
done

ls /etc/kubernetes/manifests
etcd.yml  haproxy.yml  keepalived.yml  kube-apiserver.yml  kube-controller-manager.yml  kube-scheduler.yml
  • 若IP与教学设定不同的话,请记得修改 YAML 文件。
  • kube-apiserver 中的NodeRestriction 请参考 Using Node Authorization

产生一个用来加密 Etcd 的 Key:

head -c 32 /dev/urandom | base64

注意每台master节点需要用一样的 Key。

在/etc/kubernetes/目录下,建立encryption.yml的加密 YAML 文件:

cat <<EOF > /etc/kubernetes/encryption.yml
kind: EncryptionConfig
apiVersion: v1
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys
            - name: key1
              secret: odUWVO3oVVNkgIwZmua8SThkOYPccrpJINyZcKVZvFA=
      - identity: {}
EOF

Etcd 资料加密可参考这篇 Encrypting data at rest。

在/etc/kubernetes/目录下,建立audit-policy.yml的进阶稽核策略 YAML 档:

cat <<EOF > /etc/kubernetes/audit-policy.yml
apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
  - level: Metadata
EOF

Audit Policy 请参考这篇 Auditing

下载haproxy.cfg文件来提供给 HAProxy 容器使用:

mkdir -p /etc/haproxy/

wget "${CORE_URL}/haproxy.cfg" -O /etc/haproxy/haproxy.cfg

若与本教学 IP 不同的话,请记得修改设定档。

下载kubelet.service相关文件来管理 kubelet:

mkdir -p /etc/systemd/system/kubelet.service.d

wget "${CORE_URL}/kubelet.service" -O /lib/systemd/system/kubelet.service

wget "${CORE_URL}/10-kubelet.conf" -O /etc/systemd/system/kubelet.service.d/10-kubelet.conf

若 cluster dns或domain有改变的话,需要修改10-kubelet.conf。

最后建立 var 存放信息,然后启动 kubelet 服务:

mkdir -p /var/lib/kubelet /var/log/kubernetes /var/lib/etcd

systemctl enable kubelet.service && systemctl start kubelet.service

完成后会需要一段时间来下载镜像档与启动元件,可以利用该指令来监看:

Search

    Table of Contents