标签 kubernetes 下的文章

kubernetes 强制删除资源

# 解决办法:
    --grace-period=0 --force

kubernetes容器间网络通信不可达,但配置都正常啊

# 解决办法:
    kubernetes的默认coredns,存在解析异常的情况,需要手动删除pod,然后k8s会自动重新生成新的,网络通信恢复

正常高可用环境的kubernetes集群出现异常,连接8443端口失败,kubelet服务报错Failed creating a mirror pod for pods already exists

# 解决办法:
    重启docker服务

failed to read pod IP from plugin/docker: NetworkPlugin cni failed on the status hook for pod "nginx-ingress-controller-7bff4d7c6-n7g62_default": CNI failed to retrieve network namespace path: cannot find network namespace for the terminated container "c366cb025fb0d73569707170e7ab10528c74222681bf7e6df347374fe83a6b83"

# 解决办法:

Failed to get system container stats for "/system.slice/docker.service": failed to get cgroup stats for "/system.slice/docker.service": failed to get cgroup stats for "/system.slice/docker.service": failed to get container info for "/system.slice/docker.service": unknown container "/system.slice/docker.service"

# 解决办法:
    添加额外参数:
cat <<EOF > /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"
EOF

删除pv失败,并且状态为Terminating(persistentvolume/pvc-ba6ae684-7237-43ab-91b3-750eaf16811d 30Gi RWO Delete Terminating logging/data-elasticsearch-data-0 managed-nfs-storage 2d)

# 解决办法:
    kubectl patch pv pvc-ba6ae684-7237-43ab-91b3-750eaf16811d -p '{"metadata":{"finalizers":null}}'
    kubectl patch pvc pvc-ba6ae684-7237-43ab-91b3-750eaf16811d -p '{"metadata":{"finalizers":null}}'
    kubectl patch pod db-74755f6698-8td72 -p '{"metadata":{"finalizers":null}}'
    then you can delete them
    kubectl delete pv/pvc-ba6ae684-7237-43ab-91b3-750eaf16811d
# 参考链接:
    https://github.com/kubernetes/kubernetes/issues/69697

删除namespace cert-manager失败,一直Terminating

# 解决办法:
    kubectl get namespace rook-ceph -o json > tmp.json
    then edit tmp.json and remove "kubernetes"
    kubectl proxy
    curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json http://127.0.0.1:8001/api/v1/namespaces/cert-manager/finalize
    或者
    curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json https://10.0.4.13:8443/k8s/clusters/c-xk82n/v1/namespaces/cert-manager/finalize
# 参考链接:
    https://github.com/kubernetes/kubernetes/issues/60807

NetworkPlugin cni failed to set up pod "elasticsearch-master-0_logging" network: open /run/flannel/subnet.env: no such file or directory

# 原因
    pod启动用户没有root文件/run/flannel/subnet的访问权限

0/6 nodes are available: 3 Insufficient memory, 3 node(s) had taints that the pod didn't tolerate(k8s总共6个节点,3个内存不足,3个节点有污点,pod部署失败)

# 解决办法:
    提升node节点内存即可

StorageClass.storage.k8s.io "managed-nfs-storage" is invalid: parameters: Forbidden: updates to parameters are forbidden.

# 解决办法:
    kubectl replace -f storage-class.yaml --force

lvl=eror msg="failed to search for dashboards" logger=provisioning.dashboard type=file name=istio error="database is locked"

# 解决办法:
    https://github.com/grafana/grafana/issues/16638

安装prometheus-operator,报错manifest_sorter.go:175: info: skipping unknown hook: "crd-install",Error: unable to build kubernetes objects from release manifest: [unable to recognize "": no matches for kind "Alertmanager" in version "monitoring.coreos.com/v1", unable to recognize "": no matches for kind "Prometheus" in version "monitoring.coreos.com/v1", unable to recognize "": no matches for kind "PrometheusRule" in version "monitoring.coreos.com/v1", unable to recognize "": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1"]

# 解决办法:
    kubectl create namespace monitoring
    kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/master/example/prometheus-operator-crd/alertmanager.crd.yaml
    kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/master/example/prometheus-operator-crd/prometheus.crd.yaml
    kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/master/example/prometheus-operator-crd/prometheusrule.crd.yaml
    kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/master/example/prometheus-operator-crd/servicemonitor.crd.yaml
    kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/master/example/prometheus-operator-crd/podmonitor.crd.yaml
    helm install prometheus-operator --namespace monitoring micro/prometheus-operator -f prometheus-operator.yaml

filebeat输出到logstash报错Exiting: error unpacking config data: more than one namespace configured accessing 'output' (source:'filebeat.yml')

# 解决办法:
    # filbeat.yaml中,设置如下:
    output.file.enabled: false
    output.elasticsearch.enabled: false
    output.logstash.enabled: true

如何在service内部实现session保持呢?当然是在service的yaml里进行设置啦。

# 解决办法:
    # 在service的yaml的sepc里加入以下内容:
    sessionAffinity: ClientIP
    sessionAffinityConfig:
        clientIP:
        timeoutSeconds: 10800

上次咨询的容器无法使用动态增加的cpu问题,我这边已经解决了。

# 解决办法:
    1、使用docker container update和重启容器都无法解决,
    2、taskset -pc pid  #即使设置为0-7,最终pid还是只能使用0-3
    # 原因是:/sys/fs/cgroup/cpuset/docker/cpuset.cpus的内容还是0-3,解决步骤:
    1、echo 0-7 > /sys/fs/cgroup/cpuset/docker/cpuset.cpus #手动更改为0-7(才能使用新增加的cpu核数)
    2、echo 0-7 >/sys/fs/cgroup/cpuset/docker/containerpid/cpuset.cpus

service headless类型的服务,不提供负载均衡,直接返回后端endpoints的ip列表

# 解决办法:
    # 手动将pod的dns地址拼接比如nacos-0.nacos-headless.online-shop-test.svc.cluster.local,nacos-1.nacos-headless.online-shop-test.svc.cluster.local,nacos-2.nacos-headless.online-shop-test.svc.cluster.local,提供给应用使用
    # 应用自动解析nacos-headless,动态将返回的ip列表,与实际工作端口拼接,作为连接配置项
    # In your StatefulSet manifest try to specify:
        serviceName: busy-headless
    # The headless service must exist before the StatefulSet, and is responsible for the network identity of the set.

使用helm创建elasticsearch集群,使用腾讯云cfs(nfs)作为持久化存储的时候

# 问题详情:
    "type": "server", "timestamp": "2021-04-22T07:07:51,641Z", "level": "ERROR", "component": "o.e.b.ElasticsearchUncaughtExceptionHandler", "cluster.name": "elasticsearch", "node.name": "elasticsearch-master-0", "message": "uncaught exception in thread [main]", 
    "stacktrace": ["org.elasticsearch.bootstrap.StartupException: ElasticsearchException[failed to bind service]; nested: AccessDeniedException[/usr/share/elasticsearch/data/nodes];",
    "at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:163) ~[elasticsearch-7.11.2.jar:7.11.2]",
    "at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150) ~[elasticsearch-7.11.2.jar:7.11.2]",
    "at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:75) ~[elasticsearch-7.11.2.jar:7.11.2]",
    "at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:116) ~[elasticsearch-cli-7.11.2.jar:7.11.2]",
    "at org.elasticsearch.cli.Command.main(Command.java:79) ~[elasticsearch-cli-7.11.2.jar:7.11.2]",
    "at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:115) ~[elasticsearch-7.11.2.jar:7.11.2]",
    "at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:81) ~[elasticsearch-7.11.2.jar:7.11.2]",
    "Caused by: org.elasticsearch.ElasticsearchException: failed to bind service",
# 解决办法
    找到PV对应服务器上的目录,更改权限即可(chmod -R 777 els)。

使用腾讯云cbs、cbs(csi)、cfs、cos作为持久化存储时

# 需要注意,如果使用cbs、cbs、cbs(csi),pv创建的时候,需要指定size为10的倍数,最大为16000GB
# 如果使用cfs作为持久化存储,注意主账号对cfs创建数量限制阈值,以及nfs挂载目录属组要跟容器的进程id属组权限一致
# 如果使用cos 挂载参数需要指定 -oallow_other(允许其他用户访问挂载文件夹)
# 参考链接:
    https://cloud.tencent.com/document/product/436/6883#.E5.B8.B8.E7.94.A8.E6.8C.82.E8.BD.BD.E9.80.89.E9.A1.B9

使用jenkins docker官方镜像启动,初次启动一直停留在刷新登录页

# 解决办法
    initContainers:
      - name: alpine
        image: alpine:latest
        imagePullPolicy: IfNotPresent
        command: ["sh", "-c", "chown -R 1000:1000 /opt; sed -i 's/updates.jenkins.io/mirrors.tuna.tsinghua.edu.cn\\/jenkins\\/updates/g' /opt/hudson.model.UpdateCenter.xml; true"]

k8s中jenkins master和jenins agent,安装jenkins kubernete plugin后

# configureClouds 配置
# 配置kubernetes集群
# 配置pod模板
    (注意默认已有一个jenkins/inbound-agent:4.3-4 name: "jnlp"镜像,页面上不显示,但执行jenkins 任务,就会显示该pod)
    如果使用自定义的agent镜像,需要设置Container Template中的名称一定为为jnlp,来覆盖默认的jenkins/inbound-agent:4.3-4,否则始终执行默认的jenkins/inbound-agent:4.3-4

Dockerfile中的环境变量问题

# Dockerfile中的env,是设置环境变量,而且from会被继承的。

k8s部署了service模式type类型为LoadBalancer的ingress-controller,web通过ingress配置外网域名对外提供服务:

# 问题详细:
一般情况下,新建的pod如果访问此web服务,新建的pod应该配置访问此web服务的k8s内部svc地址
但甲方说新建生产环境,不会再这个k8s下,所以打算配置此web的外网https地址,实际配置完毕后发现此集群内的大部分node和大部分node上的pod访问此域名的https失败
然而所有节点访问此域名的http协议地址却是正常的。

此时集群内node访问https直接集群内就被劫持了,没有走正常的互联网访问线路

# 解决办法:
    ingress-controller 的 svc 配置externalTrafficPolicy 为cluster
    而关于externalTrafficPolicy的cluster与local的差异,请自行官方查询,
    # 参考链接
        https://www.starbugs.net/index.php/2020/09/30/k8s%E4%B8%ADservice%E7%9A%84%E7%89%B9%E6%80%A7service-spec-externaltrafficpolicy%E5%AF%B9ingress-controller%E7%9A%84%E5%BD%B1%E5%93%8D/

# 后找到大佬的一部分讲解:
    We're also seeing this as an issue at DigitalOcean. It's a concern not just for load-balancer TLS termination, but also for supporting proxy protocol as encouraged in ( https://kubernetes.io/docs/tutorials/services/source-ip/ ). Traffic addressed to the LB ip from within the cluster never reaches the load-balancer, and the required proxy header isn't applied, causing a protocol violation.
    The in-tree AWS service type loadbalancer supports proxy protocol and TLS termination, but because they populate status.loadbalancer.ingress.hostname rather than .ip they avoid this bug/optimization.
    We're willing to put together a PR to address this there's interest from sig-network to accept it. We've considered a kube-proxy flag to disable the optimization, or the more complex option of extending v1.LoadBalancerIngress to include feedback from the cloud provider.

# 参考链接
    https://github.com/kubernetes/kubernetes/issues/66607?spm=a2c4g.11186623.2.8.765e7a47mxR9Qr
    https://help.aliyun.com/document_detail/171437.html

链接: https://pan.baidu.com/s/1g54U6lls-5LgcxkVRjBBXA 提取码: nafb

序言:
下面是使用kubeadm自动化安装三master控制节点,多node(worker)工作节点教程
kubernetes中涉及证书内容,如果你想直接签发10年证书,可以先阅读下末尾内容,再从开头进行阅读
本教程使用的etcd是通过kubeadm自动部署k8s pod到三个master上的,如果想使用外部etcd集群,可以先阅读下末尾内容,再从开头进行阅读
另外不论是docker版本、k8s各组件版本、以及第三方应用版本,都应该是互相匹配且支持的,否则无法组合,共同工作
另外各版本的命令、参数因版本的不同,会有不同差异,使用时请-help或者查阅官方详细文档
建议整体阅读,有大致理解了解以后,再进行试验
如果完全重新安装,建议完全清理以前生成的文件,以及重启相关的服务,最好重启服务器,生产环境中,记得要定期备份etcd数据等
一、基础环境
#环境
kubernetes v1.14.2(注意kubelet client跟server最好版本一致)
kubeadm 默认证书有效期为1年
linux CentOS 64 Linux release 7.5.1804 (Core)
192.168.10.241 master01
192.168.10.242 master02
192.168.10.243 master03
192.168.10.244 node01
192.168.10.245 node02
192.168.10.246 node03
#所有节点设置各自的hostname(hostname最好不要包含特殊字符比如下滑线,kubeadm会对此有校验)
hostnamectl set-hostname master01
hostnamectl set-hostname master02
hostnamectl set-hostname master03
hostnamectl set-hostname node01
hostnamectl set-hostname node02
hostnamectl set-hostname node03
#所有节点加入/etc/hosts解析
cat <<EOF >> /etc/hosts
192.168.10.241 master01
192.168.10.242 master02
192.168.10.243 master03
192.168.10.244 node01
192.168.10.245 node02
192.168.10.246 node03
EOF
#所有节点永久关闭防火墙(非常不建议内网k8s集群之间架设有防火墙“端口贼多”,k8s对外服务上架设防火墙就好)
systemctl stop firewalld
systemctl disable firewalld
#所有节点永久关闭selinux
sed -i 's/^SELINUX=.*$/SELINUX=disabled/' /etc/selinux/config
reboot #查看当前状态getenforce
#所有节点关闭swap,并设置其他一些内核参数,内核参数范例并不完整,请切合实际修改
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
vm.swappiness=0
EOF
sysctl --system #生效所有配置,查看所有参数sysctl -a
swapoff -a #临时关闭配置文件“/etc/fstab”中所有的交换空间
sed -i 's/^\/dev\/mapper\/centos-swap/#&/' /etc/fstab #永久关闭swap
#所有节点所有节点安装docker,具体安装过程请详见官方教程:https://docs.docker.com/install/linux/docker-ce/centos/,还需要参考k8s官网https://kubernetes.io/docs/setup/cri/#docker
echo "nameserver 114.114.114.114" >> /etc/resolv.conf
yum install -y yum-utils  device-mapper-persistent-data  lvm2 && yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"exec-opts": ["native.cgroupdriver=systemd"],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
# systemctl restart docker
systemctl enable docker && systemctl restart docker
#所有节点iptables开启forward
iptables -P FORWARD ACCEPT
#所有节点开启ipvs内核模块
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules
#校验ipvs相关模块是否启用
lsmod | grep -e ip_vs -e nf_conntrack_ipv4

二、所有节点安装kubeadm、kubelet和kubectl、ipvsadm
#所有节点配置阿里云repo镜像源
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
#所有节点安装kubeadm、kubelet和kubectl、ipvsadm
yum list kubeadm --showduplicates | sort -r
yum install -y kubelet-1.14.1 kubeadm-1.14.1 kubectl-1.14.1 ipvsadm
systemctl enable kubelet && systemctl start kubelet
#配置kubelet参数
cat <<EOF > /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"
EOF

三、所有master节点配置HAproxy代理和keepalived
#所有master节点,安装haproxy docker镜像
docker pull haproxy:latest
#创建haproxy的配置文件
mkdir -pv /etc/haproxy
cat <<EOF > /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local0 err
maxconn 50000
uid 99 #nobody
gid 99 #nobody
#daemon
nbproc 1
pidfile haproxy.pid
defaults
mode http
log 127.0.0.1 local0 err
maxconn 50000
retries 3
timeout connect 5s
timeout client 30s
timeout server 30s
timeout check 2s
listen admin_stats
mode http
bind 0.0.0.0:1080
log 127.0.0.1 local0 err
stats refresh 30s
stats uri     /haproxy-status
stats realm   Haproxy\ Statistics
stats auth    admin:admin
stats hide-version
stats admin if TRUE
frontend k8smaster-haproxy-https
bind 0.0.0.0:8443
mode tcp
default_backend k8smaster-https
backend k8smaster-https
mode tcp
balance roundrobin
server master01 192.168.10.241:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
server master02 192.168.10.242:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
server master03 192.168.10.243:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
EOF
#检测配置文件错误
docker run -it --rm --name haproxy-syntax-check my-haproxy haproxy -c -f /etc/haproxy/haproxy.cfg
#启动haproxy
docker run  -d --name k8smaster-haproxy -v /etc/haproxy:/usr/local/etc/haproxy:ro -p 8443:8443 -p 1080:1080 --restart always  haproxy:latest
#重载haproxy配置
docker kill -s HUP k8smaster-haproxy
#查看haproxy日志
docker logs k8smaster-haproxy
#浏览器查看状态
http://192.168.10.241:1080/haproxy-status
http://192.168.10.242:1080/haproxy-status
http://192.168.10.243:1080/haproxy-status

#所有master节点,安装keepalived docker镜像
docker pull osixia/keepalived:latest
#所有master节点,启动keepalived docker
docker run -d --name k8smaster-keepalived --net=host --cap-add=NET_ADMIN -e KEEPALIVED_INTERFACE=ens33 -e KEEPALIVED_VIRTUAL_IPS="#PYTHON2BASH:['192.168.10.240']" -e KEEPALIVED_UNICAST_PEERS="#PYTHON2BASH:['192.168.10.241','192.168.10.242','192.168.10.243']" -e KEEPALIVED_PASSWORD=admin --restart always osixia/keepalived:latest
#查看keepalived docker日志
docker logs k8smaster-keepalived
#此时vip 192.168.10.240应该会绑定到三台的master01上
ping 192.168.10.240 #可通
#如果失败,删除命令为
docker rm -f k8smaster-keepalived
ip a del 192.168.10.240/32 dev ens33

四、配置第一个master(参数使用说明,请参考官网https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-config/#cmd-config-from-file)
#查看默认组件image list
kubeadm config images list
#查看默认配置(kubeadm config print init-defaults or kubeadm config print join-defaults),并初始化文件(详细参数配置参考https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1)
cd /root/
kubeadm config print init-defaults > k8s-init-master01.yaml
#修改k8s-init-master01.yaml配置文件
详见同级目录的k8s-init-master01.yaml文件
#提前拉取镜像
kubeadm config images pull --config k8s-init-master01.yaml
#查看vip240是否在master01上(如果不在,可以同时重启另两个master的docker keepalived服务,将vip漂移到master01上)
ip addr
docker restart k8smaster-keepalived
#初始化(如果初始化超时并失败,很可能一个原因是240的vip没有在master01上,kubelet报错连接vip失败,ip addr 可以查看ip信息)
kubeadm init --config k8s-init-master01.yaml
mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config
#systemctl status -l kubelet 会报Unable to update cni config: No networks found in /etc/cni/net.d 因为还没安装k8s的flannel cni插件
#注意保存返回的join命令
kubeadm join 192.168.10.240:8443 --token rx75vh.v77joay2977m2p5g \
--discovery-token-ca-cert-hash sha256:fc9c5027264df3320d30894078f75daf69565ac50dbb411e956493e65646e4f3 \
--experimental-control-plane
kubeadm join 192.168.10.240:8443 --token rx75vh.v77joay2977m2p5g \
--discovery-token-ca-cert-hash sha256:fc9c5027264df3320d30894078f75daf69565ac50dbb411e956493e65646e4f3
#重置节点命令是(如果全部集群重置,每个master及node节点都需要操作):
kubeadm reset -f
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm --clear
rm -rf $HOME/.kube
systemctl daemon-reload && systemctl restart kubelet
#copy证书到其他master节点,不用传输证书到node节点
cd /etc/kubernetes && tar -czvf k8s-ca.tar.gz admin.conf pki/ca.* pki/sa.* pki/front-proxy-ca.* pki/etcd/ca.* && cd ~
#scp到master02、master03,然后解压相同级别目录tar -xzvf k8s-ca.tar.gz
scp /etc/kubernetes/k8s-ca.tar.gz master02:/etc/kubernetes/
scp /etc/kubernetes/k8s-ca.tar.gz master03:/etc/kubernetes/
#解压master02、master03下的k8s-ca.tar.gz
cd /etc/kubernetes/ && tar -xzvf k8s-ca.tar.gz && cd ~
cd /etc/kubernetes/ && tar -xzvf k8s-ca.tar.gz && cd ~

五、配置第二个master(以下是使用init phase分阶段加入集群教程)
#copy k8s-init-master01.yaml为k8s-init-master02.yaml,并修改内容
具体请查看同级目录的k8s-init-master02.yaml
#初始化
#配置证书
kubeadm init phase certs all --config k8s-init-master02.yaml
kubeadm init phase etcd local --config k8s-init-master02.yaml
#初始化kubelet
kubeadm init phase kubeconfig kubelet --config k8s-init-master02.yaml
kubeadm init phase kubelet-start --config k8s-init-master02.yaml
mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config
#将etcd加入集群
kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member add master02 https://192.168.10.242:2380
#查看etcd集群已有节点
kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member list
#启动kube-apiserver、kube-controller-manager、kube-scheduler
kubeadm init phase kubeconfig all --config k8s-init-master02.yaml
kubeadm init phase control-plane all --config k8s-init-master02.yaml
#标记节点为master
#获取状态
kubectl get nodes #ROLES为none状态
#标记为master
kubeadm init phase mark-control-plane --config k8s-init-master02.yaml #ROLES为master状态
#获取状态
kubectl get nodes #ROLES为master状态

六、配置第三个master(以下是使用init phase分阶段加入集群教程)
#copy k8s-init-master02.yaml为k8s-init-master03.yaml,并修改内容
具体请查看同级目录的k8s-init-master03.yaml
#初始化
#配置证书
kubeadm init phase certs all --config k8s-init-master03.yaml
kubeadm init phase etcd local --config k8s-init-master03.yaml
#初始化kubelet
kubeadm init phase kubeconfig kubelet --config k8s-init-master03.yaml
kubeadm init phase kubelet-start --config k8s-init-master03.yaml
mkdir -p $HOME/.kube && cp -i /etc/kubernetes/admin.conf $HOME/.kube/config &&  chown $(id -u):$(id -g) $HOME/.kube/config
#将etcd加入集群
kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member add master03 https://192.168.10.243:2380
#查看etcd集群已有节点
kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member list
#启动kube-apiserver、kube-controller-manager、kube-scheduler
kubeadm init phase kubeconfig all --config k8s-init-master03.yaml
kubeadm init phase control-plane all --config k8s-init-master03.yaml
#标记节点为master
#获取状态
kubectl get nodes #ROLES为none状态
#标记为master
kubeadm init phase mark-control-plane --config k8s-init-master03.yaml #ROLES为master状态
#获取状态
kubectl get nodes #ROLES为master状态

七、安装flannel(在任意一个master节点执行)
#下载flannel的yml文件
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#查看net-conf.json的network跟你的环境网络是否同一个网段,如果不是请修改kube-falnnel.yml内容为实际网段内容
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
#flannel默认会使用主机的第一张网卡,如果你有多张网卡,需要增加参数,单独指定特定网卡名称
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.11.0-amd64
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens33
#执行安装flannel
kubectl apply -f kube-flannel.yml
#查看节点状态
kubectl get nodes #status都为Ready
kubectl get pods --all-namespaces #有很多pod
systemctl status -l kubelet #不再报cni的错误

八、在所有node节点操作
#在所有node节点上运行,master01上初始化后返回的不带有参数--experimental-control-plane的join语句
执行上面master01返回的join语句
#如果忘记加入命令,可以查询(master端查询)
kubeadm token create --print-join-command
#重置命令
kubeadm reset -f
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm --clear
rm -rf $HOME/.kube
systemctl daemon-reload && systemctl restart kubelet

九、校验是否成功(任意一个master节点执行)
#节点状态
kubectl get nodes
#组件状态
kubectl get cs
#查看所有pods
kubectl get pods --namespace kube-system -o wide
#查看pod日志
kubectl logs etcd-master02 --namespace kube-system
#查看所有服务
kubectl get svc --all-namespaces
#查看指定服务
kubectl get svc --namespace kube-system
#服务账户
kubectl get serviceaccount --all-namespaces
#查看角色
kubectl get roles --all-namespaces
#集群信息
kubectl cluster-info
#验证dns功能
kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
nslookup kubernetes.default
#检查是否创建了deployments任务:
kubectl get deployments --all-namespaces
#编辑deployments配置
kubectl edit deployments -n kube-system
检查是否创建了副本控制器ReplicationController:
kubectl get rc --all-namespaces
#检查死否创建了副本集replicasets:
kubectl get rs --all-namespaces

十、部署高可用 CoreDNS(任意一个master节点执行,如果已是高可用,不需要执行本步骤,官方参考文档https://github.com/coredns/deployment/tree/master/kubernetes)
#查看pod
kubectl get pods --all-namespaces -o wide
#发现初始安装的coredns pod都在单点master03上,那如果master03宕机,coredns的服务就挂了
#下载并生成coredns.yaml文件
wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed
wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy.sh
yum install -y epel-release && yum install -y jq && chmod u+x deploy.sh
./deploy.sh > coredns.yaml
#先删除coredns
kubectl delete -f coredns.yaml
kubectl get pods --all-namespaces -o wide
#coredns.yaml为同级目录下的coredns.yaml
#安装coredns
kubectl apply  -f coredns.yaml
kubectl get pods --all-namespaces -o wide
#验证dns功能
kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
nslookup kubernetes.default

十一、安装kubernetes dashboard(任意一个master节点执行,官方参考文档https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#deploying-the-dashboard-ui , https://github.com/kubernetes/dashboard/wiki/Creating-sample-user)
#下载kubernetes-dashboard.yaml
wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
#修改kubernetes-dashboard.yaml为同级目录下的kubernetes-dashboard.yaml内容
#安装kubernetes-dashboard
kubectl apply  -f kubernetes-dashboard.yaml
#新建dashboard-adminuser.yaml文件,内容同同级目录下的dashboard-adminuser.yaml内容
#新建dashborad管理权限用户(请注意根据自己实际需求设定)
kubectl apply  -f dashboard-adminuser.yaml
#给浏览器生成客户端证书
grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d > kubecfg.crt
grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d > kubecfg.key
openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client" #此时,可以设置导出密码,kubecfg.p12就是生成的个人证书
#浏览器导入证书kubecfg.p12
需要人工手动操作浏览器设置导入证书,如果生成的时候设置了导出密码,还需要在导入的时候输入相同密码
#导入成功后,重启浏览器,然后浏览器访问Dashboard UI
https://192.168.10.240:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
#使用token登录界面,界面输入获取的token(已经登录成功,不过这一步因为浏览器版本、品牌(谷歌火狐目前测试正常)、https证书等的原因,各种报错结果,但以上步骤确定是正确的)
#获取kuberntes-dashboard用户token
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kubernetes-dashboard | awk '{print $1}') | grep token: | awk '{print $2}'
#获取service account admin-user的Token
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') | grep token: | awk '{print $2}'
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXM4cWhkIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxYzU3MzVjMy03MmRjLTExZTktYmE3ZC0wMDBjMjk4Y2M4YjMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.DkEKxwIaSeaEWRW10RefhBGoFneF4S_A_WDhqAN1bhZDuMQY93cqm7-WIw5iMvqt6SWGZSyb8KsaGUNR5ISmg5SAuLc6TUezzCyGJuntoTQRLYN0NIipbCEPj7OWGTVjiChr0Ss4X4opDpBUvQ7OkL-UzSQLpYOtSGYFPKa9CXUF5vjnNa4ova5KO61HJLInMZ-4XkPyWubsoyqihPVHXu36TnWJ0pEmpLxt9NhdCykUy1Oxcojj0r889cl5hUiLCl2Wk3mlMs3azC1pCOvRY0mcLmzz8g4OihVYMc5FK0rqG6LQ4K9SHpwB0AZQnhgzC5feHMGL9o5A2W-qek2uWQ
#使用kubeconfig文件登录(User in kubeconfig file need either username & password or token,这里我们使用token,参考链接https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/)
DASHBOARD_TOCKEN=$(kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') | grep token: | awk '{print $2}')
kubectl config set-cluster kubernetes --server=https://192.168.10.240:8443 --kubeconfig=/root/dashboard-admin.conf
kubectl config set-credentials dashboard-admin --token=$DASHBOARD_TOCKEN --kubeconfig=/root/dashboard-admin.conf
kubectl config set-context dashboard-admin@kubernetes --cluster=kubernetes --user=dashboard-admin --kubeconfig=/root/dashboard-admin.conf
kubectl config use-context dashboard-admin@kubernetes --kubeconfig=/root/dashboard-admin.conf
生成的dashboard-admin.conf即可用于kubeconfig方式登录dashboard
#注意,以上是api方式访问kubernetes dashboard,当然也可以create nginx ingress for dashboard,但不如api方式更直接,毕竟ingress挂了,也就没法ingress方式访问dashboard了

十二、模拟master01故障
#master01上执行
shutdown -h now
#需要过一段时间,k8s才会检测到master01 not ready
#浏览器重新打开https://192.168.10.240:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 看是否正常
#dashborad节点菜单项上master01已就绪状态变成Unknown
#其他正常master执行kubectl get nodes看结果
#master01的status状态变为NotReady
#查看pod是否正常
kubectl get pods --namespace kube-system -o wide
#其他服务都正常,表明kubernetesHA高可用模式成功
#当然现在重新启动master01(没有破坏过master01的数据,只是做了重启),重启服务器完毕后,整个集群的状态又会自动恢复正常。
#为了模拟更真实的故障恢复,我们破坏master01的数据更彻底些
kubeadm reset -f
#再次查询集群状态等
kubectl get nodes #master01的status状态变为NotReady
kubectl get pods --namespace kube-system -o wide

十三、模拟master01故障以后的恢复
#首先在一台正常master上运行下面的命令获取etcd集群中故障member的ID(正常master节点执行)
ETCD=`docker ps|grep etcd|grep -v POD|awk '{print $1}'`
docker exec -it ${ETCD}   etcdctl   --endpoints https://127.0.0.1:2379   --ca-file /etc/kubernetes/pki/etcd/ca.crt   --cert-file /etc/kubernetes/pki/etcd/peer.crt   --key-file /etc/kubernetes/pki/etcd/peer.key   cluster-health
#移除故障节点的etcd(正常master节点执行)
ETCD=`docker ps|grep etcd|grep -v POD|awk '{print $1}'`
docker exec -it ${ETCD}   etcdctl   --endpoints https://127.0.0.1:2379   --ca-file /etc/kubernetes/pki/etcd/ca.crt   --cert-file /etc/kubernetes/pki/etcd/peer.crt   --key-file /etc/kubernetes/pki/etcd/peer.key member remove 6bb5472fc24f7d4c
docker exec -it ${ETCD}   etcdctl   --endpoints https://127.0.0.1:2379   --ca-file /etc/kubernetes/pki/etcd/ca.crt   --cert-file /etc/kubernetes/pki/etcd/peer.crt   --key-file /etc/kubernetes/pki/etcd/peer.key   cluster-health
#重新加入正常的机器(要与原来master01主机名、IP一致),并且复用ca证书、k8s-init-master01.yaml
#注意修改initial-cluster: "master01=https://192.168.10.241:2380" 为
initial-cluster: "master01=https://192.168.10.241:2380,master02=https:/192.168.10..242:2380,master03=https:192.168.10.10.243:2380"
initial-cluster-state: existing
#重置master01(之后都在master01上执行)
#kubeadm reset -f
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm --clear
rm -rf $HOME/.kube
systemctl daemon-reload && systemctl restart kubelet
#重新做一遍master01初始化
#记得重新copy正常master上的ca证书等
cd /etc/kubernetes/ && tar -xzvf k8s-ca.tar.gz && cd ~
#配置证书
kubeadm init phase certs all --config k8s-init-master01.yaml
kubeadm init phase etcd local --config k8s-init-master01.yaml
#初始化kubelet
kubeadm init phase kubeconfig kubelet --config k8s-init-master01.yaml
kubeadm init phase kubelet-start --config k8s-init-master01.yaml
mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config
#将etcd加入集群
#查看etcd集群已有节点
kubectl exec -n kube-system etcd-master02 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.242:2379 member list
#加入集群
kubectl exec -n kube-system etcd-master02 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.242:2379 member add master01 https:/192.168.10..241:2380
#查看etcd集群已有节点
kubectl exec -n kube-system etcd-master02 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.242:2379 member list
#启动kube-apiserver、kube-controller-manager、kube-scheduler
kubeadm init phase kubeconfig all --config k8s-init-master01.yaml
kubeadm init phase control-plane all --config k8s-init-master01.yaml
#标记节点为master
kubectl get nodes #ROLES为none状态
kubeadm init phase mark-control-plane --config k8s-init-master01.yaml #ROLES为master状态
kubectl get nodes #ROLES为master状态
#查看恢复是否正常(如果失败,还需重新删除坏的etcd,然后再来一遍)
kubectl get nodes #master01 status变成ready
kubectl get pods --namespace kube-system -o wide
#成功恢复

十四、安装helm(kubernetes的包管理器,教程是关于helm2的,helm3版本已发生改变,省掉了till端)
#前提条件:
必须安装了kubernetes集群
必须拥有本地配置好的kubectl
#安装client端(Helm CLI)
#脚本安装
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get > get_helm.sh
chmod u+x get_helm.sh
./get_helm.sh
#二进制安装
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.0-linux-amd64.tar.gz
tar -xzvf helm-v2.14.0-linux-amd64.tar.gz
cp linux-amd64/helm /usr/local/bin/helm &&  cp linux-amd64/tiller /usr/local/bin/tiller
#安装server端(tiller是服务端组件,会安装到kubernetes集群里)
#安装ssl/tls的tiller(https://helm.sh/docs/using_helm/#using-ssl-between-helm-and-tiller)
cd /etc/kubernetes/pki && mkdir helm
cd helm
#制作CA RSA私钥
openssl genrsa -out ./ca.key.pem 4096
#制作CA根证书
openssl req -key ca.key.pem -new -x509 -days 7300 -sha256 -out ca.cert.pem -extensions v3_ca -subj "/C=CN/O=HELM/CN=HELM"
#生成tiller RSA私钥
openssl genrsa -out ./tiller.key.pem 4096
#生成helm RSA私钥
openssl genrsa -out ./helm.key.pem 4096
#生成tiller私钥的签名请求对(csr)
openssl req -key tiller.key.pem -new -sha256 -out tiller.csr.pem -subj "/C=CN/O=HELM/CN=TILLER"
#生成helm私钥的签名请求(csr)
openssl req -key helm.key.pem -new -sha256 -out helm.csr.pem -subj "/C=CN/O=HELM/CN=HELM"
#使用CA根证书对tiller的签名请求(csr)签名
#openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365
#默认情况下,Helm 客户端通过隧道(即 kube 代理)127.0.0.1 连接到 Tiller。 在 TLS 握手期间,通常提供主机名(例如 example.com),对证书进行检查,包括附带的信息。 但是,由于通过隧道,目标是 IP 地址。因此,要验证证书,必须在 Tiller 证书中将 IP 地址 127.0.0.1 列为 IP 附带备用名称(IP SAN: IP subject alternative name)。
例如,要在生成 Tiller 证书时将 127.0.0.1 列为 IP SAN:
echo subjectAltName=IP:127.0.0.1 > extfile.cnf
openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365 -extfile extfile.cnf
#使用CA根证书对helm的签名请求(csr)签名
openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in helm.csr.pem -out helm.cert.pem  -days 365
#查看证书内容命令
openssl x509 -text -noout -in tiller.cert.pem
#初始化tiller(注意helm客户端版本要跟服务端tiller images版本兼容)
cd ~
helm version(注意helm客户端版本要跟服务端tiller images版本兼容)
#无安全认证
helm init --history-max=0 --debug --upgrade --service-account tiller  --tiller-namespace kube-system --tiller-image gcr.azk8s.cn/google_containers/tiller:v2.14.0 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
#启用TLS安全认证(后续教程启用了TLS)
helm init --history-max=0 --debug --upgrade --service-account tiller  --tiller-namespace kube-system --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.0 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts --tiller-tls --tiller-tls-cert /etc/kubernetes/pki/helm/tiller.cert.pem --tiller-tls-key /etc/kubernetes/pki/helm/tiller.key.pem --tiller-tls-verify --tls-ca-cert /etc/kubernetes/pki/helm/ca.cert.pem
#使用谷歌默认地址,可能网络不通(https://kubernetes-charts.storage.googleapis.com)
helm init --history-max=0 --debug --upgrade --service-account tiller  --tiller-namespace kube-system --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.0 --tiller-tls --tiller-tls-cert /etc/kubernetes/pki/helm/tiller.cert.pem --tiller-tls-key /etc/kubernetes/pki/helm/tiller.key.pem --tiller-tls-verify --tls-ca-cert /etc/kubernetes/pki/helm/ca.cert.pem
#kubernetes上给tiller新建账户和角色(helm-tiller.yaml详见同级目录的helm-tiller.yaml)
kubectl apply -f helm-tiller.yaml
#kubectl delete -f helm-tiller.yaml
#查看授权是否成功
kubectl get deploy --namespace kube-system   tiller-deploy  --output yaml | grep serviceAccount
#配置client tls
#执行 helm ls 会报错:Error: transport is closing,这是因为您的 Helm 客户端没有正确的证书来向 Tiller 进行身份验证。
helm ls --debug
helm ls --tls --tls-ca-cert /etc/kubernetes/pki/helm/ca.cert.pem --tls-cert /etc/kubernetes/pki/helm/helm.cert.pem --tls-key /etc/kubernetes/pki/helm/helm.key.pem --debug
#更快捷的方式是
\cp -f /etc/kubernetes/pki/helm/ca.cert.pem $HOME/.helm/ca.pem
\cp -f /etc/kubernetes/pki/helm/helm.cert.pem $HOME/.helm/cert.pem
\cp -f /etc/kubernetes/pki/helm/helm.key.pem  $HOME/.helm/key.pem
helm ls --tls --debug
#验证
helm version --tls --debug
kubectl get pods -n kube-system | grep tiller
kubectl -n kube-system get deployment
kubectl logs $(kubectl get pods -n kube-system | grep tiller | awk '{print $1}') -n kube-system
#查看服务
kubectl get svc  -n kube-system | grep tiller
#验证端口
kubectl get pods tiller-deploy-c595846c-vf4vr --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}' -n kube-system
#如何删除和重置
kubectl delete deployment tiller-deploy -n kube-system
kubectl delete service tiller-deploy -n kube-system
kubectl delete -f helm-tiller.yaml
rm -rf $HOME/.helm
或者
helm reset -f --tls && helm reset --remove-helm-home --tls(存在无法连接tiller pod,reset失败的情况,只能使用上面的办法删除)
#使用helm
helm search
helm repo list
helm repo update
helm list --tls
#因为kubernetes集群开启了rbac,所以安装的时候需要创建rbac权限
helm install stable/nginx-ingress  --name nginx-ingress --tls --debug --set rbac.create=true
#查看状态
helm status nginx-ingress --tls

十五、使用kubectl,对rc、deployment方式部署的pod进行滚动更新或者回滚
# 如果你使用ReplicationController创建的pod可以使用kubectl rollingupdate命令滚动升级,如果使用的是Deployment创建的Pod可以直接修改yaml文件后执行kubectl apply即可。
# Deployment已经内置了RollingUpdate strategy,因此不用再调用kubectl rollingupdate命令,升级的过程是先创建新版的pod将流量导入到新pod上后销毁原来的旧的pod。
# Rolling Update适用于Deployment、Replication Controller,官方推荐使用Deployment而不再使用Replication Controller。
# 要在没有中断的情况下更新服务,请kubectl支持所谓的滚动更新,它一次更新一个容器,而不是同时关闭整个服务。
Replication Controller方式:
# 在线更新
kubectl rolling-update NAME NEW_NAME --image=IMAGE:TAG
or
kubectl rolling-update NAME -f FILE
# 遇到问题后,回滚
kubectl rolling-update my-nginx --rollback
deployment方式:
# 范例
1、新建deployment:webserver,replicas=10,image=tomcat。
2、滚动更新应用镜像为:nginx
kubectl path deployment webserver -p '{"spec":{"temple":{"spec:{"containers":[{"name":"webserver","image":"nginx"}]}"}}}'
3、观察Replicasets的变化,可发现升级后会创建新的Replicasets,删除老的Replicasets实例,滚动创建新实例。

十六、使用kubeadm方式进行kubernetes版本升级
#https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade-1-15/
#https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/
#https://github.com/kubernetes/kubeadm/issues/1322
#https://github.com/kubernetes/kubernetes/pull/69366
#https://juejin.im/post/5c9ce517e51d452b837c959e
#获取最新kubeadm最新版本
yum list --showduplicates kubeadm --disableexcludes=kubernetes
#升级第一个控制节点(master01执行)
#安装最新版本kubeadm
yum install -y kubeadm-1.15.0-0 --disableexcludes=kubernetes
#验证下载是否有效并具有预期版本
kubeadm version
#获取升级计划
kubeadm upgrade plan
#选择要升级到的版本,然后运行相应的命令
kubeadm upgrade apply v1.15.0
#手动升级您的CNI提供程序插件
#按需操作
#升级控制端上的kubelet和kubectl
yum install -y kubelet-1.15.0-0 kubectl-1.15.0-0 --disableexcludes=kubernetes
#重启kubelet
systemctl restart kubelet
#升级其他控制节点(其他master节点执行)
#与第一个控制节点操作相同但使用:
kubeadm upgrade node 代替 kubeadm upgrade apply
#查看kubeadm-config
kubectl -n kube-system get cm kubeadm-config -oyaml
#编辑添加内容
ClusterStatus: |
nodeRegistration:
criSocket: /var/run/dockershim.sock
apiEndpoints:
master01:
advertiseAddress: 192.168.10.241
bindPort: 6443
master02:
advertiseAddress: 192.168.10.242
bindPort: 6443
master03:
advertiseAddress: 192.168.10.243
bindPort: 6443
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterStatus
#如果没有上面内容则执行kubeadm upgrade node会报错:
unable to fetch the kubeadm-config ConfigMap: failed to get node registration: node master02 doesn't have kubeadm.alpha.kubernetes.io/cri-socket annotation
unable to fetch the kubeadm-config ConfigMap: failed to getAPIEndpoint: failed to get APIEndpoint information for this node
#升级工作节点(node节点执行)
#安装最新版本kubeadm
yum install -y kubeadm-1.15.0-0 --disableexcludes=kubernetes
#排空node节点(master端执行)
#通过将有负载的节点标记为不可调度并逐出工作负载来准备节点以进行维护
kubectl drain node01 --ignore-daemonsets
#升级kubelet配置
kubeadm upgrade node
#升级kubelet和kubectl
yum install -y kubelet-1.15.x-0 kubectl-1.15.x-0 --disableexcludes=kubernetes
#重启kubelet
systemctl restart kubelet
#恢复节点(master端执行)
kubectl uncordon node01

十七、kubeadm证书有效期问题
# https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/
# https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/
kubeadm 默认证书为一年,一年过期后,会导致api service不可用,使用过程中会出现:x509: certificate has expired or is not yet valid
kubeadm部署的kubernets证书一直都是个诟病,默认都只有一年有效期,kubeadm 1.14.x安装后有部分证书还是一年有效期,但个别证书已修改为10年有效期,但对我们使用来说,一年有效期还是一个比较的坑,需要进行调整。
修改kubeadm 1.14.x源码,调整证书过期时间
kubeadm1.14.x 安装过后crt证书如下所示
/etc/kubernetes/pki/apiserver.crt
/etc/kubernetes/pki/front-proxy-ca.crt         #10年有效期
/etc/kubernetes/pki/ca.crt                     #10年有效期
/etc/kubernetes/pki/apiserver-etcd-client.crt
/etc/kubernetes/pki/front-proxy-client.crt     #10年有效期
/etc/kubernetes/pki/etcd/server.crt
/etc/kubernetes/pki/etcd/ca.crt                #10年有效期
/etc/kubernetes/pki/etcd/peer.crt              #10年有效期
/etc/kubernetes/pki/etcd/healthcheck-client.crt
/etc/kubernetes/pki/apiserver-kubelet-client.crt
如上所示,除了标注说明的证书为10年有效期,其余都是1年有效期,我们查看下原先调整证书有效期的源码,克隆kubernetes 源码,切换到1.14.1 tag 查看:
代码目录: staging/src/k8s.io/client-go/util/cert/cert.go
# 那么解决方法大致两种:
一种,调整证书有效期,重新编译:http://team.jiunile.com/blog/2018/12/k8s-kubeadm-ca-upgdate.html
# 修改证书有效期为10年
# github下载kubernetes1.14.8版本

# 所有版本都需要修改的
vim cmd/kubeadm/app/util/pkiutil/pki_helpers.go
NotAfter:     time.Now().Add(duration365d).UTC(),
改为
NotAfter:     time.Now().Add(duration365d * 10).UTC(),
# 1.14.0以前版本额外需要修改的
vim staging/src/k8s.io/client-go/util/cert/cert.go
NotAfter:     time.Now().Add(duration365d).UTC(),
改为
NotAfter:     time.Now().Add(duration365d * 10).UTC(),

NotAfter:  time.Now().Add(time.Hour * 24 * 365),
改为
NotAfter:  time.Now().Add(time.Hour * 24 * 3650),
# 使用官方容器编译kubeadm
docker pull mirrorgooglecontainers/kube-cross:v1.12.10-1
docker run -it --rm -v /appservice/kubernetes-1.14.8:/go/src/k8s.io/kubernetes mirrorgooglecontainers/kube-cross:v1.12.10-1 /bin/sh
cd /go/src/k8s.io/kubernetes
# 编译kubeadm, 这里主要编译kubeadm即可
make all WHAT=cmd/kubeadm GOFLAGS=-v
# 补充参考
# # 编译kubelet
#     make all WHAT=cmd/kubelet GOFLAGS=-v
# # 编译kubectl
#     make all WHAT=cmd/kubectl GOFLAGS=-v
# 编译产物在容器目录/go/src/k8s.io/kubernetes/_output/bin/kubeadm下,或者/go/src/k8s.io/kubernetes/_output/local/bin/linux/amd64下
# 在挂载目录/appservice/kubernetes-1.14.8/_output/local/bin/linux/amd64下
# 退出容器
exit
# 备份原先kubeadm命令,然后使用新的替换
cp /usr/bin/kubeadm /usr/bin/kubeadm.$(date +%Y%m%d%H%M) \
&& cp /appservice/kubernetes-1.14.8/_output/local/bin/linux/amd64/kubeadm /usr/bin/kubeadm
二种,重新签发证书:
#建议不要重新生成ca证书,因为更新了ca证书,集群节点就需要手工操作,才能让集群正常(会涉及重新join)
#操作之前,先将/etc/kubernetes/pki下的证书文件,mv到其它文件夹,作个临时备份,不要删除。
kubeadm alpha phase certs etcd-healthcheck-client --config cluster.yaml
kubeadm alpha phase certs etcd-peer --config cluster.yaml
kubeadm alpha phase certs etcd-server --config cluster.yaml
kubeadm alpha phase certs front-proxy-client--config cluster.yaml
kubeadm alpha phase certs apiserver-etcd-client --config cluster.yaml
kubeadm alpha phase certs apiserver-kubelet-client --config cluster.yaml
kubeadm alpha phase certs apiserver --config cluster.yaml
kubeadm alpha phase certs sa --config cluster.
# 查看证书有效期
cd /etc/kubernetes/pki
openssl x509 -in ca.crt -noout -dates
openssl x509 -in apiserver.crt -noout -dates
openssl x509 -in apiserver-kubelet-client.crt -noout -dates
openssl x509 -in front-proxy-ca.crt -noout -dates
openssl x509 -in front-proxy-client.crt -noout -dates
# etcd
openssl x509 -in etcd/ca.crt -noout -dates
openssl x509 -in etcd/etcd.crt -noout -dates
# 1.8 kubelet版本及以上证书轮换 #https://kubernetes.io/zh/docs/tasks/tls/certificate-rotation/
Kubelet 使用证书进行 Kubernetes API 的认证。 默认情况下,这些证书的签发期限为一年,所以不需要太频繁地进行更新。
Kubernetes 1.8 版本中包含 beta 特性 kubelet 证书轮换, 在当前证书即将过期时, 将自动生成新的秘钥,并从 Kubernetes API 申请新的证书。 一旦新的证书可用,它将被用于与 Kubernetes API 间的连接认证。
# 启用客户端证书轮换
kubelet 进程接收 --rotate-certificates 参数,该参数决定 kubelet 在当前使用的证书即将到期时, 是否会自动申请新的证书。 由于证书轮换是 beta 特性,必须通过参数 --feature-gates=RotateKubeletClientCertificate=true 进行启用。
kube-controller-manager 进程接收 --experimental-cluster-signing-duration 参数,该参数控制证书签发的有效期限。
十八、使用外部etcd集群(仅供步骤参考,细节需要自己适配更改)
# 安装etcd
yum install -y etcd
# 使用kubeadm生成etcd的ca证书
# 生成etcd的ca证书
kubeadm init phase certs etcd-ca --config k8s-init-master09.yaml
# 或者根据配置生成所有证书
kubeadm init phase certs all --config k8s-init-master09.yaml
# 以下是docker内etcd集群才会用到
# kubeadm init phase certs etcd-server --config k8s-init-master09.yaml
# kubeadm init phase certs etcd-peer --config k8s-init-master09.yaml
# kubeadm init phase certs etcd-healthcheck-client --config k8s-init-master09.yaml
# kubeadm init phase certs apiserver-etcd-client --config k8s-init-master09.yaml
# kubeadm init phase etcd local --config k8s-init-master09.yaml
# 创建所有服务的证书
cd /etc/etcd/
mkdir ssl
cd ssl
cp /etc/kubernetes/pki/etcd/ca.* ./
# 已有ca根证书
# CA RSA私钥
ca.key
# CA根证书
ca.crt
# 生成etcd RSA私钥
openssl genrsa -out ./etcd.key 4096
# 生成etcd私钥的签名请求对(csr)
openssl req -key etcd.key -new -sha256 -out etcd.csr -subj "/C=CN/O=ETCD/CN=ETCD"
# 使用制作的CA根证书对每个签名请求(csr)签名
echo "subjectAltName=DNS:master09,IP:10.0.10.9,IP:127.0.0.1" > extfile
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in etcd.csr -extfile extfile -out etcd.crt -days 3650 # 10年
# 补充查看命令
openssl x509 -text -noout -in etcd.crt
# 将etcd.key,etcd.crt复制到/etc/kubernetes/pki/etcd下
cp etcd.* /etc/kubernetes/pki/etcd/
# 修改etcd数据目录软链到存储上
mv /var/lib/etcd /appservice/
ln -s /appservice/etcd /var/lib/etcd
# 修改etcd配置
grep -v ^# /etc/etcd/etcd.conf
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://10.0.10.9:2380"
ETCD_LISTEN_CLIENT_URLS="https://localhost:2379,https://10.0.10.9:2379"
ETCD_NAME="master09"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.0.10.9:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://10.0.10.9:2379"
ETCD_INITIAL_CLUSTER="master09=https://10.0.10.9:2380"
ETCD_ENABLE_V2="false"
ETCD_CERT_FILE="/etc/etcd/ssl/etcd.crt"
ETCD_KEY_FILE="/etc/etcd/ssl/etcd.key"
ETCD_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.crt"
ETCD_PEER_CERT_FILE="/etc/etcd/ssl/etcd.crt"
ETCD_PEER_KEY_FILE="/etc/etcd/ssl/etcd.key"
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.crt"
# 启动并设置开机启动
systemctl start etcd
systemctl enable etcd
# 注意修改k8s-init-master.yaml中的etcd配置
etcd:
external:
endpoints:
- https://10.0.10.9:2379
caFile: /etc/kubernetes/pki/etcd/ca.crt
certFile: /etc/kubernetes/pki/etcd/etcd.crt
keyFile: /etc/kubernetes/pki/etcd/etcd.key

解决办法:参考链接:https://github.com/kubernetes/kubernetes/issues/60807

kubectl get namespace cert-manager -o json > tmp.json
then edit tmp.json and remove"kubernetes"
kubectl proxy
curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json http://127.0.0.1:8001/api/v1/namespaces/cert-manager/finalize

https://www.jianshu.com/p/604a7149a632
https://www.qikqiak.com/post/install-efk-stack-on-k8s/
http://www.maogx.win/posts/45/

#在k8s集群中应用一般有如下日志输出方式:
    直接遵循docker官方建议把日志输出到标准输出或者标准错误输出
    输出日志到容器内指定目录中
    应用直接发送日志给日志收集系统

#k8s集群中的pod产生的日志(stdout/stderr)都存放在对应node的/var/lib/docker/containers/(决定于docker安装时指定的哪个是数据目录)下

#日志收集组件说明:
    elastisearch 存储收集到的日志
    kibana 可视化收集到的日志
    logstash 汇总处理日志发送给elastisearch 存储
    filebeat 读取容器或者应用日志文件处理发送给elastisearch或者logstash,也可用于汇总日志
    fluentd 读取容器或者应用日志文件处理发送给elastisearch,也可用于汇总日志
    fluent-bit 读取容器或者应用日志文件处理发送给elastisearch或者fluentd

#在进行日志收集的过程中,我们首先想到的是使用Logstash,因为它是ELK stack中的重要成员,但是在测试过程中发现,Logstash是基于JDK的,在没有产生日志的情况单纯启动Logstash就大概要消耗500M内存,在每个Pod中都启动一个日志收集组件的情况下,使用logstash有点浪费系统资源,经人推荐我们选择使用Filebeat替代,经测试单独启动Filebeat容器大约会消耗12M内存,比起logstash相当轻量级。

#Kubernetes 中比较流行的日志收集解决方案是 Elasticsearch、Fluentd 和 Kibana(EFK)技术栈,也是官方现在比较推荐的一种方案。
#Elasticsearch 是一个实时的、分布式的可扩展的搜索引擎,允许进行全文、结构化搜索,它通常用于索引和搜索大量日志数据,也可用于搜索许多不同类型的文档。
#Elasticsearch 通常与 Kibana 一起部署,Kibana 是 Elasticsearch 的一个功能强大的数据可视化 Dashboard,Kibana 允许你通过 web 界面来浏览 Elasticsearch 日志数据。
#Fluentd是一个流行的开源数据收集器,我们将在 Kubernetes 集群节点上安装 Fluentd,通过获取容器日志文件、过滤和转换日志数据,然后将数据传递到 Elasticsearch 集群,在该集群中对其进行索引和存储。

#前提,已经做了nfs的动态pv,安装好了helm、nginx-ingress
一、创建logging namespace
    kubectl apply -f namespace_logging.yaml
    or
    kubectl create namespace logging
    kubectl get ns
二、首先开始部署一个3节点的 Elasticsearch 集群
    helm repo add micro http://mirror.azure.cn/kubernetes/charts/
    helm install --name elasticsearch micro/elasticsearch --namespace logging -f ./micro-1.30.0.yaml --tls --debug
三、部署kibana
    helm install --name kibana micro/kibana --namespace logging -f ./micro-3.2.2.yaml --tls --debug
四、部署fluentd
    helm install --name fluentd-elasticsearch micro/fluentd-elasticsearch --namespace logging -f ./micro-2.0.7.yaml --tls --debug
五、访问kibana
    https://kibana.kubernetes.ingress:32443/
    创建索引

直接粘贴笔记,格式不太美观,教程原文件及yaml配置文件,可以直接百度云下载后浏览:https://pan.baidu.com/s/14KArQ7yWhqWJEgcVZrxE6Q 提取码:86mq