(二)搭建一个完成的Kubernetes/K8s集群v.1.16
单节点集群
多节点集群 注意node通过连接loadbalancer 转发到mateter 的apiserver来进行运作的
集群规划:
角色 | ip | 组件 |
---|---|---|
K8S-master1 | 192.168.0.101 | kube-apiserver kube-controller-manager kube-scheduleretcd |
K8S-master2 | 192.168.0.102 | kube-apiserver kube-controller-manager kube-scheduleretcd |
K8S-node1 | 192.168.0.103 | kubelet kube-proxy docker etcd |
K8S-node2 | 192.168.0.104 | kubelet kube-proxy docker etcd |
K8S-load-balancer | 192.168.0.106(vip)实际IP105 | Nginx L4 |
1,系统初始化
##关闭防火墙:systemctl stop firewalldsystemctl disable firewalld##关闭selinux:setenforce 0 ## 临时sed -i 's/enforcing/disabled/' /etc/selinux/config ## 永久##关闭swap:swapoff -a ## 临时vim /etc/fstab ##将swap 那一行注释掉##同步系统时间:ntpdate time.windows.com ##同步时间可能需要安装ntp服务器 同步内网时间ntpdate 192.168.0.101##添加hosts:vim /etc/hosts192.168.0.101 k8s-master1192.168.0.102 k8s-master2192.168.0.103 k8s-node1192.168.0.104 k8s-node2##修改主机名:hostnamectl set-hostname k8s-master1
2,etcd集群安装
(1)证书签发(注意 etcd集群是双向证书)
# cd TLS/etcd安装cfssl工具:# ./cfssl.sh#curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl#curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson#curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfocp -rf cfssl cfssl-certinfo cfssljson /usr/local/binchmod +x /usr/local/bin/cfssl*修改请求文件中hosts字段包含所有etcd节点IP:# vi server-csr.json (签发具体域名配置){ "CN": "etcd", "hosts": [ "192.168.0.101", "192.168.0.103", "192.168.0.104" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing" } ]}
生成ca根证书文件
{ "CN": "etcd CA", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Beijing", "ST": "Beijing" } ]}
签发etcd双向证书配置文件
{ "signing": { "default": { "expiry": "876000h" }, "profiles": { "www": { "expiry": "876000h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } }}
生成ca根证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
签发etcd证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
etcd 安装所需文件(注意文件路径)
etcd.service,/usr/lib/systemd/system,etcd/ssl/{ca,server,server-key}.pem ,/etcd/bin/etcd,/etcd/bin/etcdctl.etcd.config
[Unit]Description=Etcd ServerAfter=network.targetAfter=network-online.targetWants=network-online.target[Service]Type=notifyEnvironmentFile=/opt/etcd/cfg/etcd.confExecStart=/opt/etcd/bin/etcd \ --name=${ETCD_NAME} \ --data-dir=${ETCD_DATA_DIR} \ --listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \ --listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \ --advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \ --initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \ --initial-cluster=${ETCD_INITIAL_CLUSTER} \ --initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \ --initial-cluster-state=new \ --cert-file=/opt/etcd/ssl/server.pem \ --key-file=/opt/etcd/ssl/server-key.pem \ --peer-cert-file=/opt/etcd/ssl/server.pem \ --peer-key-file=/opt/etcd/ssl/server-key.pem \ --trusted-ca-file=/opt/etcd/ssl/ca.pem \ --peer-trusted-ca-file=/opt/etcd/ssl/ca.pemRestart=on-failureLimitNOFILE=65536[Install]WantedBy=multi-user.target
etcd.config
#[Member]ETCD_NAME="etcd-1" ##集群里节点名称(唯一)ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ##存放路径ETCD_LISTEN_PEER_URLS="https://192.168.0.101:2380" ##内部互相通信监听端口ETCD_LISTEN_CLIENT_URLS="https://192.168.0.101:2379" ##外部通信监听端口 比如面向apiserver#[Clustering]ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.0.101:2380" ##集群里内部通信端口ETCD_ADVERTISE_CLIENT_URLS="https://192.168.0.101:2379" ##集群外部通信端口ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.0.101:2380,etcd-2=https://192.168.0.103:2380,etcd-3=https://192.168.0.104:2380" ##集群里 其他节点名称 地址 和监听端口ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ## 集群内认证口令 字符串 可以随便改 但是得统一ETCD_INITIAL_CLUSTER_STATE="new" ##集群的状态 new 是新建 exsiting 表示已有集群 然后新增加
所有etcd节点
systemctl daemon-reloadsystemctl restart etcdsystemctl enable etcd##在启动的时候 其他节点会等候加入,在所有节点起来后才会启动,如有问题查询/var/log/message 系统启动日志##验证节点是否健康正常运行/opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.0.101:2379,https://192.168.0.103:2379,https://192.168.0.104:2379" cluster-health
3,master节点安装
自签api ssl 证书(注意此时跟etcd 不是用的同一套ca)
ca根证书
vim ca-config.json{ "signing": { "default": { "expiry": "876000h" }, "profiles": { "kubernetes": { "expiry": "876000h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } }}vim ca-csr.json{ "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Beijing", "ST": "Beijing", "O": "k8s", "OU": "System" } ]}
api-server
server-csr.json{ "CN": "kubernetes", ##K8S证书官方规定使用默认字段名 "hosts": [ "10.0.0.1", ##service 内部集群通信的第一个IP 地址 "127.0.0.1", "kubernetes", ##官方规定的需要添加进入证书的名称 "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local", "192.168.0.100", ##master api server 地址 包括自己本身,已经需要访问的load balance 地址(通过lb 访问可以不用添加node地址) "192.168.0.101", "192.168.0.102", "192.168.0.103", "192.168.0.104", "192.168.0.105" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing", "O": "k8s", "OU": "System" } ]}##worker-node节点 kube-proxy 证书 注意CN 字段名kube-proxy.json{ "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing", "O": "k8s", "OU": "System" } ]}
签发
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare servercfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy##生成apiserver 证书 以及kube-proxy证书
安装启动
tar zxvf k8s-master.tar.gzcd kubernetescp TLS/k8s/ssl/*.pem sslcp -rf kubernetes /optcp kube-apiserver.service kube-controller-manager.service kube-scheduler.service /usr/lib/systemd/systemsystemctl start kube-apiserversystemctl start kube-controller-managersystemctl start kube-schedulersystemctl enable kube-apiserversystemctl enable kube-controller-managersystemctl enable kube-scheduler#为kubelet TLS Bootstrapping 授权cat /opt/kubernetes/cfg/token.csv ##c47ffb939f5ca36231d9e3121a252940,kubelet-bootstrap,10001,"system:node-bootstrapper"kubectl create clusterrolebinding kubelet-bootstrap \--clusterrole=system:node-bootstrapper \--user=kubelet-bootstrap
kube-apiserver.conf
KUBE_APISERVER_OPTS="--logtostderr=false \ ##输出日志--v=2 \ ##输出日志级别--log-dir=/opt/kubernetes/logs \ ##日志存放位置--etcd-servers=https://192.168.31.61:2379,https://192.168.31.62:2379,https://192.168.31.63:2379 \ ##etcd地址--bind-address=192.168.31.61 \ ##绑定的IP,可以用公网地址--secure-port=6443 \ ##监听端口--advertise-address=192.168.31.61 \ ##通告地址,一般和本机IP一样,告诉node通过哪个IP来链接访问--allow-privileged=true \ #允许创建的容器具有超级管理员权限--service-cluster-ip-range=10.0.0.0/24 \ #service IP范围,service会分配这个IP段的IP地址--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \ #启用控制插件,属于k8s高级功能,比如资源配额限制,访问控制等--authorization-mode=RBAC,Node \ #授权模式,一般使用rbac角色来访问--enable-bootstrap-token-auth=true \ #启用bootstrap,为node用户请求自动颁发证书,在token.csv 定义具体权限内容。--token-auth-file=/opt/kubernetes/cfg/token.csv \--service-node-port-range=30000-32767 \ ## server 服务暴露的端口--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \ ##kubelet证书--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \--tls-cert-file=/opt/kubernetes/ssl/server.pem \ ##apiserver使用https证书--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \ --client-ca-file=/opt/kubernetes/ssl/ca.pem \--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \--etcd-cafile=/opt/etcd/ssl/ca.pem \ ###etcd 证书--etcd-certfile=/opt/etcd/ssl/server.pem \--etcd-keyfile=/opt/etcd/ssl/server-key.pem \--audit-log-maxage=30 \ #日志审计配置--audit-log-maxbackup=3 \--audit-log-maxsize=100 \--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
kube-controller-manager.conf 配置文件
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \ ##配置日志--v=2 \ #配置日志级别--log-dir=/opt/kubernetes/logs \ #配置日志目录--leader-elect=true \ #集群选举,api server才做高可用, kube-controller-manager本身会基于etcd来实现高可用,启用该选项即可--master=127.0.0.1:8080 \ #apiserver的IP,我们设置链接本地,8080是apiserver监听端口,它默认会开放该端口--address=127.0.0.1 \ #组件监听地址,本地即可,无需对外--allocate-node-cidrs=true \ ##允许安装cni网络的插件--cluster-cidr=10.244.0.0/16 \ ##pod的地址池--service-cluster-ip-range=10.0.0.0/24 \ #server的IP范围,和 kube-apiserverIP范围是一样的#集群签名的证书,node加入集群颁发自动颁发kubelet证书,kubelet由controller-manager颁发,controller-manager由下面配置的颁发--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \#签署service-account所需要的私钥--root-ca-file=/opt/kubernetes/ssl/ca.pem \--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \#为node颁发证书时间,10年--experimental-cluster-signing-duration=87600h0m0s"
kube-scheduler.conf
KUBE_SCHEDULER_OPTS="--logtostderr=false \--v=2 \--log-dir=/opt/kubernetes/logs \--leader-elect \ #多个scheduler集群选举--master=127.0.0.1:8080 \ #链接apiserver地址--address=127.0.0.1" #监听本地地址
4,部署node 组件
kubelet,kube-proxy,docker
4.1,安装docker
tar zxvf k8s-node.tar.gztar zxvf docker-18.09.6.tgzmv docker/* /usr/binmkdir /etc/dockermv daemon.json /etc/dockermv docker.service /usr/lib/systemd/systemsystemctl start dockersystemctl enable dockerdocker info ##查看docker信息 比如仓库配置等
4.2.安装kubelet 以及 kube-proxy(注意更改节点名称,以及部署的masterIP)
bootstrap.kubeconfig 下的server要为master的IP
kube-proxy.kubeconfig 下的server要为master的IP
kubelet.conf 下的hostname-override 注册节点名称要唯一
kube-proxy-config.yml 下的hostnameOverride 注册节点名称要唯一
配置文件后缀含义
.conf #基本配置文件
.kubeconfig #链接apiserver的配置文件
.yml #主要配置文件(动态更新配置文件)
kubernetes/
├── bin
│ ├── kubectl
│ └── kube-proxy
├── cfg
│ ├── bootstrap.kubeconfig #请求证书的配置文件
│ ├── kubelet.conf
│ ├── kubelet-config.yml#动态调整kubelet配置
│ ├── kube-proxy.conf
│ ├── kube-proxy-config.yml #动态调整proxy配置
│ └── kube-proxy.kubeconfig #是链接apiserver的组件
├── logs
└── ssl
vim kubelet.conf##输出以下内容:KUBELET_OPTS="--logtostderr=false \ #日志--v=2 \ #日志级别--log-dir=/opt/kubernetes/logs \ #日志目录--hostname-override=k8s-node1 \ #节点名称,名称必须唯一,每个节点都要改一下--network-plugin=cni \ #启用网络插件##指定配置文件路径--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \--config=/opt/kubernetes/cfg/kubelet-config.yml \--cert-dir=/opt/kubernetes/ssl \ #指定为节点颁发的证书存放目录--pod-infra-container-image=lizhenliang/pause-amd64:3.0" #启动pod的镜像,这个pod镜像主要是管理pod的命名空间
bootstrap.kubeconfig##输出以下内容:apiVersion: v1clusters:- cluster:certificate-authority: /opt/kubernetes/ssl/ca.pemserver: https://192.168.0.101:6443 #master1服务器IP(内网IP)name: kubernetescontexts:- context:cluster: kubernetesuser: kubelet-bootstrapname: defaultcurrent-context: defaultkind: Configpreferences: {}users:- name: kubelet-bootstrapuser:token: c47ffb939f5ca36231d9e3121a252940 ##token要与/opt/kubernetes/cfg/token.csv 里面的token一致##k8s为了解决kubelet颁发证书的复杂性,所以引入了bootstrap机制,自动的为将要加入到集群的node颁发kubelet证书,所有链接apiserver的都需要证书。
bootstrap工作流程(带tenken 验证,在请求通过后会生成kubelet.kubeconfig)
kubelet-config.yml#输出以下内容:kind: KubeletConfiguration #使用对象apiVersion: kubelet.config.k8s.io/v1beta1 #api版本address: 0.0.0.0 #监听地址port: 10250 #当前kubelet的端口readOnlyPort: 10255 #kubelet暴露的端口cgroupDriver: cgroupfs #驱动,要于docker info显示的驱动一致clusterDNS: - 10.0.0.2clusterDomain: cluster.local #集群域failSwapOn: false #关闭swap#访问授权authentication:anonymous:enabled: falsewebhook:cacheTTL: 2m0senabled: truex509:clientCAFile: /opt/kubernetes/ssl/ca.pem ##pod 优化参数authorization:mode: Webhookwebhook:cacheAuthorizedTTL: 5m0scacheUnauthorizedTTL: 30sevictionHard:imagefs.available: 15%memory.available: 100Minodefs.available: 10%nodefs.inodesFree: 5%maxOpenFiles: 1000000maxPods: 110
kube-proxy.kubeconfig #输出以下内容:apiVersion: v1clusters:- cluster:certificate-authority: /opt/kubernetes/ssl/ca.pem #指定caserver: https://192.168.0.101:6443 #masterIP地址(内网)name: kubernetescontexts:- context:cluster: kubernetesuser: kube-proxyname: defaultcurrent-context: defaultkind: Configpreferences: {}users:- name: kube-proxyuser:client-certificate: /opt/kubernetes/ssl/kube-proxy.pemclient-key: /opt/kubernetes/ssl/kube-proxy-key.pem
kube-proxy-config.yml#输出以下内容: kind: KubeProxyConfigurationapiVersion: kubeproxy.config.k8s.io/v1alpha1address: 0.0.0.0 #监听地址metricsBindAddress: 0.0.0.0:10249 #监控指标地址,监控获取相关信息 就从这里获取clientConnection:kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig #读取配置文件hostnameOverride: k8s-node1 #注册到k8s的节点名称唯一clusterCIDR: 10.0.0.0/24mode: ipvs #模式,使用ipvs(性能比较好),默认是IPtablesipvs:scheduler: "rr"iptables:masqueradeAll: true
安装启动
##在签发 证书的机器上分发证书到node 节点(3个证书 ca.pem,kube-proxy.pem,kube-proxy.key)cd TLS/k8sscp ca.pem kube-proxy*.pem root@192.168.31.65:/opt/kubernetes/ssl/##在nodejiqi tar zxvf k8s-node.tar.gzmv kubernetes /optcp kubelet.service kube-proxy.service /usr/lib/systemd/system##修改以下2个文件中IP地址:(master地址) grep 192 *bootstrap.kubeconfig: server: https://192.168.0.101:6443kube-proxy.kubeconfig: server: https://192.168.0.101:6443##修改以下两个文件中主机名:(改正成之前规定好的主机名)grep hostname *kubelet.conf:--hostname-override=k8s-node1 \kube-proxy-config.yml:hostnameOverride: k8s-node1##启动,设置开机启动systemctl start kubeletsystemctl start kube-proxysystemctl enable kubeletsystemctl enable kube-proxy##启动后kubne-proxy会出现Failed to delete stale service IP 10.0.0.2 connectionsyum -y install yum -y install conntrack 解决###启动后在master上kubectl get csr ## 如果启动没问题 会显示node 节点kubelet请求颁发证书##允许给node 颁发证书 后半段是get csr 显示的内容kubectl certificate approve node-csr-MYUxbmf_nmPQjmH3LkbZRL2uTO-_FCzDQUoUfTy7YjI##查看nodekubectl get node ##(会显示NotReady 不影响 这是因为还没不是cni 网络插件的原因)
4.3安装cni网络插件和flannel网络
cni是k8s的一个接口,如果需要对接k8s就需要遵循cni接口标准,部署cni主要是为了接通第三方网络
需要做的:
cni安装到每台node节点
flannel安装到master节点
4.3.1,安装cni
#下载安装包cniwget https://github.com/containernetworking/plugins/releases/download/v0.8.5/cni-plugins-linux-amd64-v0.8.5.tgz##解压安装包cnimkdir -p /opt/cni/bin #工作目录mkdir -p /etc/cni/net.d #配置文件tar -zxvf cni-plugins-linux-amd64-v0.8.5.tgz -C /opt/cni/bin
4.3.2master节点安装flannel
kubectl apply -f kubectl apply -f kube-flannel.yaml ##这个flannel只需要安装到master节点上##这个文件需要***,下载到服务器后直接执行 kubectl apply -f kube-flannel.yml(里面的镜像需要***,直接安装国外的会失败,不建议)##yaml里面的网络net-conf.json要和 cat /opt/kubernetes/cfg/kube-controller-manager.conf 里面的cluster-cidr值一致##如果不使用flannel,其他的组件也一样##安装好后,每个node都会启动一个pod
5,部署webui
官方部署:
https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/##在master安装 注意更改暴露的端口kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yamlkubectl apply -f recommended.yaml
修改部署:
kubectl apply -f dashboard.yamlkubectl get pods -n kubernetes-dashboard#输出以下内容NAME READY STATUS RESTARTS AGEdashboard-metrics-scraper-76585494d8-sbzjv 1/1 Running 0 2m6skubernetes-dashboard-5996555fd8-fc7zf 1/1 Running 2 2m6s#查看端口kubectl get pods,svc -n kubernetes-dashboard#输出以下内容NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/dashboard-metrics-scraper ClusterIP 10.0.0.8 8000/TCP 16mservice/kubernetes-dashboard NodePort 10.0.0.88 443:30001/TCP#使用任意node节点IP+端口即可访问https://nodeip:300001
我们使用token方式来登录,创建service account并绑定默认cluster-admin管理员集群角色
kubectl apply -f dashboard-adminuser.yaml#获取tokenkubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
由于证书问题 部分浏览器并不能登录 比如chorm,这时候 还需要给dashboard 签发一个自签证书 以支持多种浏览器
mkdir key && cd key#生成证书openssl genrsa -out dashboard.key 2048openssl req -new -out dashboard.csr -key dashboard.key -subj '/CN=kubernetes-dashboard-certs'openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt#删除原有的证书secretkubectl delete secret kubernetes-dashboard-certs -n kubernetes-dashboard#创建新的证书secretkubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kube-system#查看dashboard pod,v2.0是 -n kubernetes-dashboardkubectl get pod -n kube-system#重启dashboard pod,v2.0是 -n kubernetes-dashboardkubectl delete pod -n kube-system
部署DNS(DNS 是为service 提供解析 kubectl get svc里的)
功能:可以通过svc的名称去访问到svc 然后svc转发到对应的pod
kubectl apply -f coredns.yaml##注意:clusterIP要和node节点的cat /opt/kubernetes/cfg/kubelet.conf 的clusterDNS一致,否则pod会解析失败##查看dnskubectl get pods -n kube-system##输出以下内容:coredns-6d8cfdd59d-mw47j 1/1 Running 0 5m45s##测试##安装busybox工具kubectl apply -f bs.yaml##查看我们启动的podkubectl get pods##进入容器内部kubectl exec -t busybox sh##测试ping kubernetes