学堂 学堂 学堂公众号手机端

k8s+etcd集群配置(k8s etcd请求超时)

lewis 1年前 (2024-04-17) 阅读数 13 #技术
一 、 使用kubeadm 搭建 kubernetes 集群

1.1 获取kubernetes 安装包

登陆github , https://github.com/kubernetes/release


通过git clone 命令下载到linux, 进入rpm目录,安装好docker执行 docker-build.sh脚本,即可在output目录下编译出rpm包,

1.2 下载镜像

由于gci.io 是goolge的, 所以使用kubeadm init时 会出现下载不了镜像,镜像的版本会更具rpm版本不同略有不同。

通过FQ可以把镜像下载到本地, 通过docker push 到私有registry,kubeadm init 修改配置文件使用私有registry,apiserver 会启动不了

查看使用的镜像版本,kubeadm init 会出现/etc/kubernetes/manifests/ 目录,里面的json文件,可以查看image

但是还会有一些镜像无法找到,比如kubedns、pause 等, 可以在源码中找到

​​https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/images/images.go​​

二.ETCD集群配置ETCD参数说明—data-dir 指定节点的数据存储目录,这些数据包括节点ID,集群ID,集群初始化配置,Snapshot文件,若未指定—wal-dir,还会存储WAL文件;—wal-dir 指定节点的was文件的存储目录,若指定了该参数,wal文件会和其他数据文件分开存储。—name 节点名称—initial-advertise-peer-urls 告知集群其他节点url.— listen-peer-urls 监听URL,用于与其他节点通讯— advertise-client-urls 告知客户端url, 也就是服务的url— initial-cluster-token 集群的ID— initial-cluster 集群中所有节点

使用阿里云yum源

192.168.20.206 192.168.20.223 192.168.20.224 三台分别安装 etcd服务器

[root@docker1~]# yum -y install etcd

  查看etcd版本

[root@kubernetes ~]# etcdctl -v
etcdctl version: 3.0.15
API version: 2

docker1 /etc/etcd/etcd.conf配置文件

[root@docker1 ~]# grep -v "#" /etc/etcd/etcd.conf
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.20.209:2379,http://127.0.0.1:2379"

docker2 /etc/etcd/etcd.conf配置文件

[root@docker2 ~]# grep -v "#" /etc/etcd/etcd.conf 
ETCD_NAME=etcd2
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.20.223:2379,http://127.0.0.1:2379"

docker3 /etc/etcd/etcd.conf配置文件

[root@docker3 etcd]# grep -v "#" /etc/etcd/etcd.conf
ETCD_NAME=etcd3
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.20.224:2379,http://127.0.0.1:2379"

修改/usr/lib/systemd/system/etcd.service

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/etcd.conf
User=etcd
# setfailure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

重启3台etcd的服务

[root@docker1 etcd]# systemctl restart etcd.service
[root@docker2 etcd]# systemctl restart etcd.service
[root@docker3 etcd]# systemctl restart etcd.service

etcd集群操作

[root@docker1 ~]# etcdctl  member list
b6d60bb2e9e4f37c: name=etcd1 peerURLs=http://192.168.20.209:2380 clientURLs= isLeader=false
c4abafabbe0d2097: name=etcd3 peerURLs=http://192.168.20.224:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.224:2379 isLeader=false
e8f6dc6436ef6d63: name=etcd2 peerURLs=http://192.168.20.223:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.223:2379 isLeader=true
cluster

[root@docker1 ~]# etcdctl member remove b6d60bb2e9e4f37c
Removed member b6d60bb2e9e4f37c from cluster


[root@docker1 ~]# etcdctl member list
c4abafabbe0d2097: name=etcd3 peerURLs=http://192.168.20.223:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.223:2379 isLeader=false
e8f6dc6436ef6d63: name=etcd2 peerURLs=http://192.168.20.224:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.224:2379 isLeader=true


添加节点:

1. 关闭etcd1 节点的进程,模拟节点挂了
[root@docker1 ~]# systemctl stop etcd.service

2. 192.168.20.209 删除数据
[root@etcd1 ~]# rm /var/lib/etcd/default.etcd/member/* -rf

3.etcd2 添加节点
[root@etcd2 ~]# etcdctl member add etcd1 http://192.168.20.209:2380
Added member named etcd1 with ID d92ef1d9c9d9ebe7 to cluster
ETCD_NAME="etcd1"
ETCD_INITIAL_CLUSTER_STATE="existing"

状态变成 如下:
[root@docker1 ~]# etcdctl member list
c4abafabbe0d2097: name=etcd3 peerURLs=http://192.168.20.224:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.224:2379 isLeader=false
d92ef1d9c9d9ebe7[unstarted]: peerURLs=http://192.168.20.226:2380
e8f6dc6436ef6d63: name=etcd2 peerURLs=http://192.168.20.225:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.223:2379 isLeader=true


5. 修改/etc/etcd/etcd.conf ETCD_INITIAL_CLUSTER_STATE 由 new 变成 existing
此时d92ef1d9c9d9ebe7 192.168.20.226 状态为[unstarted]:

6. 重启 etcd1 的服务进程
[root@docker1 ~]# systemctl start etcd.service

7. 查看etcd 服务

[root@docker1 etcd]# etcdctl member list
5190eb3277e38296: name=etcd1 peerURLs=http://192.168.20.226:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.209:2379 isLeader=false
c4abafabbe0d2097: name=etcd3 peerURLs=http://192.168.20.224:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.224:2379 isLeader=false
e8f6dc6436ef6d63: name=etcd2 peerURLs=http://192.168.20.225:2380 clientURLs=http://127.0.0.1:2379,http://192.168.20.225:2379 isLeader=true

三 安装kubeadm

y ebtables socat

Ebtables即是以太网桥防火墙,以太网桥工作在数据链路层,Ebtables来过滤数据链路层数据包

启动kubelet客户端

[root@docker1 etcd]# systemctl start kubelet.service

[root@docker1 etcd]# systemctl enable kubelet.service

四 初始化master1
添加vip

[root@docker1 etcd]# ip addr add 192.168.20.227/24 dev ens32

[root@docker1 etcd]# kubeadm init --api-advertise-addresses=192.168.20.227 --external-etcd-endpoints=http://192.168.20.209:2379,http://192.168.20.223:2379,http://192.168.20.224:2379
Flag --external-etcd-endpoints has been deprecated, this flag will be removed when componentconfig exists
[kubeadm] WARNING: kubeadm is in alpha, please do not use it for production clusters.
[preflight] Running pre-flight checks
[preflight] Starting the kubelet service
[init] Using Kubernetes version: v1.5.3
[tokens] Generated token: "7fd3db.6c8b8f165050c555"
[certificates] Generated Certificate Authority key and certificate.
[certificates] Generated API Server key and certificate
[certificates] Generated Service Account signing keys
[certificates] Created keys and certificates in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[apiclient] Created API client, waiting for the control plane to become ready
[apiclient] All control plane components are healthy after 18.581028 seconds
[apiclient] Waiting for at least one node to register and become ready
[apiclient] First node is ready after 4.009030 seconds
[apiclient] Creating a test deployment
[apiclient] Test deployment succeeded
[token-discovery] Created the kube-discovery deployment, waiting for it to become ready
[token-discovery] kube-discovery is ready after 2.004518 seconds
[addons] Created essential addon: kube-proxy
[addons] Created essential addon: kube-dns

Your Kubernetes master has initialized successfully!

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
http://kubernetes.io/docs/admin/addons/

You can now join any number of machines by running the following on each node:

kubeadm join --token=7fd3db.6c8b8f165050c555 192.168.20.227


--api-advertise-addresses 支持多个ip,但是会导致kubeadm join无法正常加入, 所以对外服务只配置为一个vip


如果使用flannel 网络,使用:
kubeadm init --api-advertise-addresses=192.168.20.227 --external-etcd-endpoints=http://192.168.20.209:2379,http://192.168.20.223:2379,http://192.168.20.224:2379 --pod-network-cidr=10.244.0.0/16

五,部署其他master(docker2 docker3)

安装rpm包(kubeadm, )
[root@docker2 ~]# rpm -ivh kubeadm-1.6.0-0.alpha.0.2074.a092d8e0f95f52.x86_64.rpm kubectl-1.5.1-0.x86_64.rpm kubelet-1.5.1-0.x86_64.rpm kubernetes-cni-0.3.0.1-0.07a8a2.x86_64.rpm
[root@docker2 ~]# systemctl start kubelet.service ; systemctl enable kubelet.service
[root@docker2 ~]# scp -r 192.168.20.209:/etc/kubernetes/* /etc/kubernetes/

kube-controller-manager kube-scheduler 通过 --leader-elect实现了分布式锁. 所以三个master节点可以正常运行

六 查看各master 进程、pod情况
192.168.20.209 master,启动了 192.168.20.227 vip

192.168.20.223 master

192.168.20.224 master

192.168.20.209 查看启动的node节点, 和vip地址

查看master 节点pod 情况, kube-dns pod 没有启动,应为没有配置网络

七 创建POD网络

创建好集群后,为了能让容器进行跨主机通讯还要部署 Pod 网络,这里使用官方推荐的 weave 方式,也可以采用 flannel,以下为 weave 示例
只在:docker1上执行。

[root@docker1 ~]#docker pull weaveworks/weave-kube:1.9.2
[root@docker1 ~]#docker tag weaveworks/weave-kube:1.9.2 weaveworks/weave-kube:1.9.2
[root@docker1 ~]#docker rmi weaveworks/weave-kube:1.7.2

[root@docker1 ~]# kubectl create -f weave-kube.yaml
或者 kubectl create -f https://git.io/weave-kube


如果使用 flannel 网络
wget https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel.yml
kubectl create -f kube-flannel.yml

八 采用daemonsets 方式,实现核心组件高可用dns 组件,只在docker 上执行
1.方案一,直接replicas
[root@docker1 ~]# kubectl scale deploy/kube-dns --replicas=3 --namespace=kube-system
或者         kubectl scale deployment/kube-dns --replicas=3 --namespace=kube-system

使用最新的 dns

Kubernetes DNS pod拥有3个容器 - kubedns,dnsmasq和一个名为healthz的健康检查。kubedns进程监视Kubernetes主服务和端点的更改,并维护内存中查找结构来服务DNS请求。dnsmasq容器添加DNS缓存以提高性能。healthz容器在执行双重健康检查(对于dnsmasq和kubedns)时提供单个健康检查端点。

1.删除自带dns组件
[root@docker1 ~]# kubectl delete deploy/kube-dns svc/kube-dns -n kube-system

2.下载最新的dns组件
[root@docker1 ~]# cd /root/dns/

for i in Makefile kubedns-controller.yaml.base kubedns-svc.yaml.base transforms2salt.sed transforms2sed.sed; do
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/$i
done
[root@docker1 dns]# ls
kubedns-controller.yaml.base kubedns-svc.yaml.base kubernetes-dashboard.yaml Makefile transforms2salt.sed transforms2sed.sed


3. 修改本地环境
[root@docker1 ~]# kubectl get svc |grep kubernetes
kubernetes 10.0.96.1 <none> 443/TCP 6d

[root@docker1 dns]# DNS_SERVER_IP=10.0.96.10
[root@docker1 dns]# DNS_DOMAIN=cluster.local

修改transforms2sed.sed里面2个变量为实际网段及搜索域,修改前如下
[root@k8s-master kubernetes]# cat transforms2sed.sed
s/__PILLAR__DNS__SERVER__/$DNS_SERVER_IP/g
s/__PILLAR__DNS__DOMAIN__/$DNS_DOMAIN/g
/__PILLAR__FEDERATIONS__DOMAIN__MAP__/d
s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: __SOURCE_FILENAME__/g

修改后如下
[root@k8s-master kubernetes]# cat transforms2sed.sed
s/__PILLAR__DNS__SERVER__/10.254.0.10/g
s/__PILLAR__DNS__DOMAIN__/cluster.local/g
/__PILLAR__FEDERATIONS__DOMAIN__MAP__/d
s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: __SOURCE_FILENAME__/g

编译
[root@k8s-master kubernetes]# make
sed -f transforms2salt.sed kubedns-controller.yaml.base | sed s/__SOURCE_FILENAME__/kubedns-controller.yaml.base/g > kubedns-controller.yaml.in
sed -f transforms2salt.sed kubedns-svc.yaml.base | sed s/__SOURCE_FILENAME__/kubedns-svc.yaml.base/g > kubedns-svc.yaml.in
sed -f transforms2sed.sed kubedns-controller.yaml.base | sed s/__SOURCE_FILENAME__/kubedns-controller.yaml.base/g > kubedns-controller.yaml.sed
sed -f transforms2sed.sed kubedns-svc.yaml.base | sed s/__SOURCE_FILENAME__/kubedns-svc.yaml.base/g > kubedns-svc.yaml.sed


4,修改RC和SVC文件
#现在编辑文件kubedns-controller.yaml.sed删除(这是用#注释)volume的配置,以避免两个问题:
#1.错误: error validating "kubedns-controller.yaml.sed.bak": error validating data: found invalid field optional for v1.ConfigMapVolumeSource; if you choose to ignore these errors, turn validation off with --validate=false
#2.创建容器后, tail /var/log/messages, 显示错误: configmaps "kube-dns" not found
[root@docker1 ~]# cat kubedns-controller.yaml.sed

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
spec:
strategy:
rollingUpdate:
maxSurge: 10%
maxUnavailable: 0
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
spec:
containers:
- name: kubedns
image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.12.1
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
livenessProbe:
httpGet:
path: /healthcheck/kubedns
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /readiness
port: 8081
scheme: HTTP
initialDelaySeconds: 3
timeoutSeconds: 5
args:
- --domain=cluster.local.
- --dns-port=10053
- --config-dir=/kube-dns-config
- --v=2
env:
- name: PROMETHEUS_PORT
value: "10055"
ports:
- containerPort: 10053
name: dns-local
protocol: UDP
- containerPort: 10053
name: dns-tcp-local
protocol: TCP
- containerPort: 10055
name: metrics
protocol: TCP
- name: dnsmasq
image: gcr.io/google_containers/k8s-dns-dnsmasq-amd64:1.12.1
livenessProbe:
httpGet:
path: /healthcheck/dnsmasq
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --cache-size=1000
- --server=/cluster.local/127.0.0.1#10053
- --server=/in-addr.arpa/127.0.0.1#10053
- --server=/ip6.arpa/127.0.0.1#10053
- --log-facility=-
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
# see: https://github.com/kubernetes/kubernetes/issues/29055 for details
resources:
requests:
cpu: 150m
memory: 10Mi
- name: sidecar
image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.12.1
livenessProbe:
httpGet:
path: /metrics
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --v=2
- --logtostderr
- --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local,5,A
- --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local,5,A
ports:
- containerPort: 10054
name: metrics
protocol: TCP
resources:
requests:
memory: 20Mi
cpu: 10m
dnsPolicy: Default # Don't use cluster DNS.


[root@docker1 dns ]# cat kubedns-svc.yaml.sed

apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.254.0.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP

 [root@docker1 dns]# kubectl create -f kubedns-controller.yaml.sed
deployment "kube-dns" created

[root@docker1 dns]# kubectl create -f kubedns-svc.yaml.sed
service "kube-dns" created

 [root@docker1 dns]# kubectl get service --all-namespaces
 NAMESPACE       NAME    CLUSTER-IP    EXTERNAL-IP    PORT(S)    AGE
 default kubernetes    10.96.0.1 <none>      443/TCP              59m
 kube-system kube-dns 10.96.0.10 <none>      53/UDP,53/TCP          17s

测试创建2个pod

[root@docker1 ~]# cat centos.yaml

apiVersion: v1
kind: Service
metadata:
name: my-centos-svc
labels:
app: centos
spec:
ports:
- port: 80
selector:
app: centos
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-centos
spec:
replicas: 1
template:
metadata:
labels:
app: centos
spec:
containers:
- name: centos
image: docker.cinyi.com:443/centos7.3
ports:
- containerPort: 80

[root@docker1 ~]# vim nginx.yaml

apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
ports:
- port: 80
selector:
app: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.cinyi.com:443/senyint/nginx
ports:
- containerPort: 80

[root@docker1 ~]# kubectl create -f nginx.yaml -f centos.yaml

方案二、采用采用​​daemonsets​​方式,实现核心组件实现高可用,

DaemonSet能够让所有(或者一些特定)的Node节点运行同一个pod。当节点加入到kubernetes集群中,pod会被(DaemonSet)调度到该节点上运行,当节点从kubernetes集群中被移除,被(DaemonSet)调度的pod会被移除

DaemonSet 与 nodeSelector 合用 ,并且在使用的node 打上label,这样就可以指定到不同的node节点上。

[root@docker1 dns]# cat kubends.yaml

apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.96.0.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP

---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
spec:
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
spec:
nodeSelector:
zone: master
containers:
- name: kubedns
image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.12.1
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
livenessProbe:
httpGet:
path: /healthcheck/kubedns
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /readiness
port: 8081
scheme: HTTP
initialDelaySeconds: 3
timeoutSeconds: 5
args:
- --domain=cluster.local.
- --dns-port=10053- --v=2
env:
- name: PROMETHEUS_PORT
value: "10055"
ports:
- containerPort: 10053
name: dns-local
protocol: UDP
- containerPort: 10053
name: dns-tcp-local
protocol: TCP
- containerPort: 10055
name: metrics
protocol: TCP
- name: dnsmasq
image: gcr.io/google_containers/k8s-dns-dnsmasq-amd64:1.12.1
livenessProbe:
httpGet:
path: /healthcheck/dnsmasq
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --cache-size=1000
- --server=/cluster.local/127.0.0.1#10053
- --server=/in-addr.arpa/127.0.0.1#10053
- --server=/ip6.arpa/127.0.0.1#10053
- --log-facility=-
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
resources:
requests:
cpu: 150m
memory: 10Mi
- name: sidecar
image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.12.1
livenessProbe:
httpGet:
path: /metrics
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --v=2
- --logtostderr
- --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local,5,A
- --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local,5,A
ports:
- containerPort: 10054
name: metrics
protocol: TCP
resources:
requests:
memory: 20Mi
cpu: 10m
dnsPolicy: Default # Don't use cluster DNS.

创建 dns service 和 daemonset ,创建完成 没有dns pod的信息,需要告诉在那个节点启动,使用 kubecet label 命令

[root@docker1 dns]# kubectl create -f /root/dns/kubends.yaml

#zone=master,在dns.yaml文件的 nodeSelector 定义

[root@docker1 dns]# kubectl label node docker1 zone=master

执行完成后,只在docker1 上启动dns pod,为了冗余,需要在 docker2 docker3 也启动

[root@docker2 ~]# kubectl label node docker1 zone=master

[root@docker3 ~]# kubectl label node docker1 zone=master

kube-discovery,kube-discovery 主要负责集群密钥的分发,如果这个组件不正常, 将无法正常新增节点kubeadm join

docker1上直接执行

方案一,直接添加副本数,出现错误,只能存在唯一的 一个node上

kubectl scale deploy/kube-discovery --replicas=3 -n kube-system
报错信息为:
pod (kube-discovery-1769846148-55sjr) failed to fit in any node fit failure summary on nodes : MatchNodeSelector (2), PodFitsHostPorts (1)

方案二

#1. 导出kube-discovery配置
kubectl get deploy/kube-discovery -n kube-system -o yaml > /data/kube-discovery.yaml
#2. 把Deployment类型改为DaemonSet,并加上master nodeSelector
#3. 删掉自带kube-discovery
  kubectl delete deploy/kube-discovery -n kube-system
#4. 部署kube-discovery
kubectl apply -f kube-discovery.yaml
#5. 打docker1 docker2 docker3 标记
[root@docker1 ~]# kubectl label node docker1 role=discovery
[root@docker2 ~]# kubectl label node docker2 role=discovery
[root@docker3 ~]# kubectl label node docker3 role=discovery

#6.配置中删除了 annotaions 选项,不然只能启动一个descovery pod

注意: nodeSelector 标记变成了  zone=descovery 

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: 2017-03-09T10:07:44Z
generation: 1
labels:
component: kube-discovery
k8s-app: kube-discovery
kubernetes.io/cluster-service: "true"
name: kube-discovery
tier: node
name: kube-discovery
namespace: kube-system
resourceVersion: "85792"
selfLink: /apis/extensions/v1beta1/namespaces/kube-system/deployments/kube-discovery
uid: 3d1333e4-04b0-11e7-ae57-0050568450f4
spec:
selector:
matchLabels:
component: kube-discovery
k8s-app: kube-discovery
kubernetes.io/cluster-service: "true"
name: kube-discovery
tier: node
template:
metadata:
creationTimestamp: null
labels:
component: kube-discovery
k8s-app: kube-discovery
kubernetes.io/cluster-service: "true"
name: kube-discovery
tier: node
spec:
nodeSelector:
role: discovery
containers:
- command:
- /usr/local/bin/kube-discovery
image: gcr.io/google_containers/kube-discovery-amd64:1.0
imagePullPolicy: IfNotPresent
name: kube-discovery
ports:
- containerPort: 9898
hostPort: 9898
name: http
protocol: TCP
resources: {}
securityContext:
seLinuxOptions:
type: spc_t
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /tmp/secret
name: clusterinfo
readOnly: true
dnsPolicy: ClusterFirst
hostNetwork: true
restartPolicy: Always
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: clusterinfo
secret:
defaultMode: 420
secretName: clusterinfo



九 vip192.168.20.227 漂移

到目前为止,三个master节点 相互独立运行,互补干扰.​​kube-apiserver​​​作为核心入口, 可以使用keepalived 实现高可用,​​kubeadm join暂时不支持负载均衡的方式​

3台mater安装keepalived

yum -y install keepalived

以下是三台服务器的keepalived 配置文件

docker1 keepalived 配置文件

global_defs {
router_id LVS_k8s
}

vrrp_script CheckK8sMaster {
script "curl -k https://192.168.20.227:6443"
interval 3
timeout 9
fall 2
rise 2
}

vrrp_instance VI_1 {
state MASTER
interface ens32
virtual_router_id 61
priority 115
nopreempt

authentication {
auth_type PASS
auth_pass 123456
}

unicast_peer {
192.168.20.223
192.168.20.224
}
virtual_ipaddress {
192.168.20.227/24
}
track_script {
CheckK8sMaster
}

}

docker2 keepalived 配置文件

global_defs {
router_id LVS_k8s
}

vrrp_script CheckK8sMaster {
script "curl -k https://192.168.20.227:6443"
interval 3
timeout 9
fall 2
rise 2
}

vrrp_instance VI_1 {
state BACKUP
interface ens32
virtual_router_id 61
priority 110
nopreempt

authentication {
auth_type PASS
auth_pass 123456
}

unicast_peer {
192.168.20.224
192.168.20.209
}
virtual_ipaddress {
192.168.20.227/24
}
track_script {
CheckK8sMaster
}

}

docker3 keeplived 配置文件

global_defs {
router_id LVS_k8s
}

vrrp_script CheckK8sMaster {
script "curl -k https://192.168.20.227:6443"
interval 3
timeout 9
fall 2
rise 2
}

vrrp_instance VI_1 {
state MASTER
interface ens32
virtual_router_id 61
priority 100
nopreempt

authentication {
auth_type PASS
auth_pass 123456
}

unicast_peer {
192.168.20.223
192.168.20.209
}
virtual_ipaddress {
192.168.20.227/24
}
track_script {
CheckK8sMaster
}

}

十 验证

加入节点

[root@docker4 ~]# yum install -y ebtables socat  docker
[root@docker4 ~]# scp 192.168.20.209:/root.*.rpm  /root/
[root@docker4 ~]# ls
kubectl-1.5.1-0.x86_64.rpm    kubeadm-1.6.0-0.alpha.0.2074.a092d8e0f95f52.x86_64.rpm    kubelet-1.5.1-0.x86_64.rpm    kubernetes-cni-0.3.0.1-0.07a8a2.x86_64.rpm
[root@docker4 ~]# rpm -ivh  *.rpm
[root@docker4 ~]# systemctl start kubelet.service
[root@docker4 ~]# systemctl enable kubelet.service
[root@docker4 ~]# kubeadm join --token=7fd3db.6c8b8f165050c555 192.168.20.227


登陆到 docker1 上查看 docker4 是否加入到集群

192.168.20.209 master docker1 关机

192.168.20.223 /var/log/messages 日志,192.168.20.227 自动添加


master1 docker 服务器关机, 所有docker节点状态都为丢失,使用docker2,登陆到pod中, 解析可以访问。

kubernetes 安装dashboard
[root@docker2 ~]# wget https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml

[root@docker2 ~]# kubectl create -f kubernetes-dashboard.yaml
[root@docker2 ~]#kubectl describe service kubernetes-dashboard --namespace=kube-system

IE访问:

​​http://192.168.20.227:31766​​

安装headper插件方便监控流量图

Heapster:对集群中各node上cAdvisor的数据采集汇聚的系统,通过访问node上kubelet的API,在通过kubelet调用cAdvisor的API来采集该节点上所有容器的性能数据,

heapster对性能数据进行聚合,并将结果保存到后端存储系统中,Headper支持多种后端存储系统,包括memory ,InfluxDB, BigQuery, 目前Heapster项目主页为

​​https://github.com/kubernetes/heapster​​

InfluxDB: 是分布式时序数据库,每条记录都带有时间戳属性,主要用于实时数据采集、事件跟踪记录、存储时间图表,原始数据等。 InfluxDB 提供了 RESt API 用于数据

的存储和查询, 主页是 http://influxdb.com

Grafana: 通过dashboard 将influxDB中的实时数据展现成图表或者曲线等形式, 主页是 http://grafana.org

[root@docker2 ~]# git clone https://github.com/kubernetes/heapster
[root@docker2 ~]# cd /root/heapster/deploy/kube-config/influxdb/
[root@docker2 ~]# ls
grafana-service.yaml heapster-controller.yaml heapster-service.yaml influxdb-grafana-controller.yaml influxdb-service.yaml

由于apiserver 使用的vip,并且是容器化后,默认是127.0.0.1:8080 端口, heapster-controller.yaml文件需要连接apiserver:8080端口, telnet 192.168.20.227 超时,所以使用
loadbalancer IP地址,前提是dns能够正常解析。其实 10.96.0.1 就是apiserver的服务端口,端口为443
登录到nginx pod中,测试dns解析结果

修改 heapster-controller.yaml 文件,注意 dns域名要写完整。kubernetes.default.svc.cluster.local

spec:
containers:
- name: heapster
image: kubernetes/heapster:canary
imagePullPolicy: IfNotPresent
command:
- /heapster
- --source=kubernetes:https://kubernetes.default.svc.cluster.local
- --sink=influxdb:http://monitoring-influxdb.kube-system.svc.cluster.local:8086

[root@docker2 ~]#  kubectl create -f  /root/heapster/deploy/kube-config/influxdb/

登录dashboard 映射的nodeport端口,查看监控是否正常,端口为30263.

Kubernetes Nginx Ingress

Kubernetes 暴露服务的方式目前只有三种:LoadBlancer Service、NodePort Service、Ingress

由于pod 和 service 是 kubernetes 集群范围内的虚拟的概念,所以集群外的客户端无法通过pod ip地址或者service的虚拟IP地址和虚拟端口号访问它们,可以通过将pod 或者service

的端口号映射到宿主机。

1. 将容器应用的端口号映射到物理机

通过设置pod级别的hostNetwork=true,将pod端口映射到物理机上,在容器的ports定义部分如果不指定hostPort,默认hostPort 等于containerPort,如果指定了hostPort,则hostPort必须等于containerPort的值

apiVersion: v1
kind: Pod
metadata:
name: webapp
labels:
app: webapp
spec:
hostNetwork: true
containers:
- name: webapp
image: docker.cinyi.com:443/senyint/nginx
ports:
- containerPort: 80
hostPort: 80

在docker4 上查看端口

2.将service端口映射到物理机

通过设置nodePort映射到物理机上,如果不指定nodeport 将随机分配 30001---30761之间的端口。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: tomcat
tier: frontend
spec:
containers:
- name: tomcat
image: docker.cinyi.com:443/tomcat
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-server
spec:
type: NodePort
ports:
- port: 11111
targetPort: 8080
nodePort: 30001
selector:
tier: frontend

Ingress 就是能利用 Nginx 方向代理 service 名字和端口,Ingress将不同的URl访问请求转发到后端不同的service,实现http层的业务路由机制,

Ingress的实现需要通过Ingress的定义与Ingress Controller的定义结合起来,才能形成完整的http负载转发功能。

使用Ingress 解决2个问题:

1. pod 迁移问题,Pod挂掉时自动从其他机器启动一个新的,所以pod的ip地址发生变化,

2.采用nodeport 暴露server的 nodeport端口,会出现物理机的 端口原来越多,不方便管理。

安装 Ingress Nginx

1.部署默认后端,如果访问的域名不存在,全部转到默认后端

地址:https://github.com/kubernetes/ingress/tree/master/examples/deployment/nginx

[root@docker1]# cat /root/default-backend.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: default-http-backend
labels:
k8s-app: default-http-backend
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: default-http-backend
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
image: gcr.io/google_containers/defaultbackend:1.0
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: kube-system
labels:
k8s-app: default-http-backend
spec:
ports:
- port: 80
targetPort: 8080
selector:
k8s-app: default-http-backend

[root@docker1~ ]# kubcectl create -f default-backend.yaml

2. 部署 Ingress Controller

我在 nginx-ingress-controller.yaml 文件的 kind 使用了DaemonSet,通过nodeselect zone属性,让它在3台master (apiserver)运行,

apiVersion: extensions/v1beta1
kind: DaemonSet
#kind: Deployment
metadata:
name: nginx-ingress-controller
labels:
k8s-app: nginx-ingress-controller
namespace: kube-system
spec:
# replicas: 1
template:
metadata:
labels:
k8s-app: nginx-ingress-controller
spec:
nodeSelector:
zone: nginx-ingress
hostNetwork: true
terminationGracePeriodSeconds: 60
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2
name: nginx-ingress-controller
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
livenessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 1
ports:
- containerPort: 80
hostPort: 80
- containerPort: 443
hostPort: 443
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend

[root@docker1 ~]# kubectl create -f nginx-ingress-controller.yaml

指定运行的机器,如果已经运行到了其他node节点,使用 kubectl delete pods pod名称 删除。
[root@docker1 ~]# kubectl lable node docker1 zone=nginx-ingress
[root@docker2 ~]# kubectl lable node docker2 zone=nginx-ingress
[root@docker3 ~]# kubectl lable node docker3 zone=nginx-ingress

部署Ingress, 查看所有的service

编写yaml文件,文件内容是域名 - 服务 - 端口

[root@docker1 ~]# vim show-ingress.yaml 

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dashboard-nginx-ingress
namespace: kube-system
spec:
rules:
- host: dashboard.feng.com
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 80
- host: nginx.feng.com
http:
paths:
- backend:
serviceName: my-nginx-svc
servicePort: 80

[root@docker1~]# kubectl create -f show-ingress.yaml

[root@docker1 ~]# kubectl get ingress --namespace=kube-system -o wide
NAME              HOSTS                    ADDRESS                     PORTS AGE
dashboard-nginx-ingress dashboard.feng.com,nginx.feng.com 192.168.20.209,192.168.20.223,192.168.20.224   80 19h

2个域名,指定到3个IP上,映射到宿主机的80端口上。

如果是不同namespaces 命名空间下的服务, 可以写2个 ingress yaml文件

[root@docker1 ~]# cat dashboard-ingressA.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dashboard-ingressa
namespace: kube-system
spec:
rules:
- host: dashboard.feng.com
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 80
- host: nginx.feng.com
http:
paths:
- backend:
serviceName: monitoring-grafana
servicePort: 80

[root@docker1 ~]# cat dashboard-ingressB.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dashboard-ingressb
namespace: test
spec:
rules:
- host: imweb.feng.com
http:
paths:
- backend:
serviceName: im-web
servicePort: 80

[root@docker1 ~]# kubectl create -f default-backend.yaml -f nginx-ingress-controller.yaml -f dashboard-ingressA.yaml -f dashboard-ingressB.yaml 
deployment "default-http-backend" created
service "default-http-backend" created
daemonset "nginx-ingress-controller" created
ingress "dashboard-ingressa" created
ingress "dashboard-ingressb"
[root@docker1 ~]# kubectl get ingress --all-namespaces
NAMESPACE NAME HOSTS ADDRESS PORTS AGE
kube-system dashboard-ingressa dashboard.feng.com,nginx.feng.com 80 27s
test dashboard-ingressb imweb.feng.com 80

修改client host后,访问域名

想不使用 Ingress, 直接使用nginx, 设置hostNetwork=true,创建pod和service后,进入到pod中,nslookup 不能解析其他service 的域名。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: docker.cinyi.com:443/senyint/nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
selector:
app: nginx



版权声明

本文仅代表作者观点,不代表博信信息网立场。

热门