1 容器编排和k8s(Kubernetes)
1.1 容器部署的困局
容器部署的困境
1 10台服务器如何编排 .资源能不能真的利用,真的需要所有服务器都上线,动态调整,如何调正,如果有2W台服务器怎么办
2 容器合理的编排,容器的分配就叫容器编排k8s就是一个容器编排的工具
1.2 容器编排工具解决了哪些问题
1 自动化容器的部署和复制
2随时扩展或收缩容器规模
3 容器分组group,并且提供容器间的负载均衡(实现nginx功能)
4 实时监控,即时故障发现,自动替换
1.3 容器编排工具的比较
docker -compose 单机编排工具
docker-swarm docker官方提供的集群编排工具
k8s 谷歌官方提供,底层基于docker是docker-swarm的强大的对手,谷歌基于自己运维经验开发,由于有更多的市场经验,更加稳定,容器管理被k8s一家独大,docker-swarm慢慢边缘化
2 k8s是的基本概念
2.1 pod
1 pod是k8s可以控制的最小单元,一个pod就是一个进程
2 pod下的容器可以互相通信,每个pod有独立的ip
3 不在同一个pod下的容器需要使用kuber-proxy进行通信
4 pod是容器的容器 里面可以有多个容器
5 pod都是部署完整的应用或模块
2.2 容器
指代都是dokcer容器
2.3 label
标签标识每个pod的不同作用
2.4 Replication controller
复制控制器再mastr的主节点上对pod的数量进行监控,pod失去了控制,就会把他去掉,再创建一个
2.5 Service
按某些功能分组(pod分组)
2.6 master
master 中控台所有的请求都会经过master
2.7 node
工作节点需要向 k8smaster注册
3 k8s集群安装
3.1 安装方式
1 使用kubeadmin 通过离线镜像安装
2 使用阿里云共有平台k8s,钞能力
3 通过yum官方仓库安装
4 二进制包形式安装
3.2 安装k8s集群
所需文件百度盘连接
链接: https://pan.baidu.com/s/1vCGy853LBxh2LrQsO1RBKQ 提取码: xn52
1. 环境准备
准备不低于2台虚机。 1台 master,其余的做node
OS: Centos7.5 mini install。 最小化安装。配置节点IP
主机名IP配置
at2192.168.4.1304C 8G
at3192.168.4.1314C 8G
分别设置主机名为master1 node1 ... 时区
timedatectl set-timezone Asia/Shanghai#都要执行
hostnamectl set-hostname master1#master1执行
hostnamectl set-hostname node1#node1执行
在所有节点/etc/hosts中添加解析,master1,node1
127.0.0.1localhostlocalhost.localdomainlocalhost4localhost4.localdomain4
::1localhostlocalhost.localdomainlocalhost6localhost6.localdomain6
192.168.4.130matser1
192.168.4.131node1
关闭所有节点的seliux以及firewalld
sed-i's/SELINUX=enforcing/SELINUX=disabled/g'/etc/selinux/config
setenforce0
systemctl disable firewalld
systemctlstopfirewalld
2. 安装docker
使用文件docker-ce-18.09.tar.gz,每个节点都要安装。
tar-zxvfdocker-ce-18.09.tar.gz
cddocker
rpm-Uvh* 或者yumlocalinstall*.rpm进行安装,yum命令可以自动解决依赖
dockerversion#安装完成查看版本
启动docker,并设置为开机自启
systemctlstartdocker && systemctl enable docker
输入docker info,==记录Cgroup Driver== Cgroup Driver: cgroupfs docker和kubelet的cgroup driver需要一致,如果docker不是cgroupfs,则执行
cat<<EOF>/etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=cgroupfs"]
}
EOF
systemctldaemon-reload&&systemctlrestartdocker
2. 安装kubeadm,kubectl,kubelet
使用文件kube114-rpm.tar.gz,每个节点都要安装
kubeadm是集群部署工具
kubectl是集群管理工具,通过command来管理集群
kubelet的k8s集群每个节点的docker管理服务
tar-zxvfkube114-rpm.tar.gz
cdkube114-rpm
yumlocalinstall*.rpm进行安装,yum命令可以自动解决依赖
关闭swap,及修改iptables,不然后面kubeadm会报错
swapoff-a
vi/etc/fstab#swap一行注释
cat<<EOF>/etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
EOF
sysctl--system
3. 导入镜像
使用文件k8s-114-images.tar.gz flannel-dashboard.tar.gz,每个节点都要执行
节点较少,就不搭建镜像仓库服务了,后续要用的应用镜像,每个节点都要导入
docker load -i k8s-114-images.tar.gz
docker load -i flannel-dashboard.tar.gz
一共9个镜像,分别是
k8s.gcr.io/kube-apiserver:v1.14.1
k8s.gcr.io/kube-controller-manager:v1.14.1
k8s.gcr.io/kube-scheduler:v1.14.1
k8s.gcr.io/kube-proxy:v1.14.1
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.10
k8s.gcr.io/coredns:1.3.1
k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
quay.io/coreos/flannel:v0.11.0-amd64
4. kubeadm init 部署master节点
只在master执行。此处选用最简单快捷的部署方案。etcd、api、controller-manager、 scheduler服务都会以容器的方式运行在master。etcd 为单点,不带证书。etcd的数据会挂载到master节点/var/lib/etcd
init部署是支持etcd 集群和证书模式的,配置方法见我1.9的文档,此处略过。
init命令注意要指定版本,和pod范围
kubeadminit--kubernetes-version=v1.14.1--pod-network-cidr=10.244.0.0/16
YourKubernetescontrol-planehasinitializedsuccessfully!
Tostartusingyourcluster,youneedtorunthefollowingasaregularuser:
mkdir-p$HOME/.kube
sudocp-i/etc/kubernetes/admin.conf$HOME/.kube/config
sudochown$(id-u):$(id-g)$HOME/.kube/config
Youshouldnowdeployapodnetworktothecluster.
Run"kubectl apply -f [podnetwork].yaml"withoneoftheoptionslistedat:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Thenyoucanjoinanynumberofworkernodesbyrunningthefollowingoneachasroot:
kubeadmjoin192.168.4.130:6443--token911xit.xkp2gfxbvf5wuqz7\
--discovery-token-ca-cert-hashsha256:23db3094dc9ae1335b25692717c40e24b1041975f6a43da9f43568f8d0dbac72
记下join的命令,后续node节点加入的时候要用到,如果报错在命令后增加
--ignore-preflight-errors=all ,用于忽略掉环境上的错误
执行提示的命令,保存kubeconfig
mkdir-p$HOME/.kube
sudocp-i/etc/kubernetes/admin.conf $HOME/.kube/config
sudochown$(id-u):$(id-g)$HOME/.kube/config
此时执行kubectl get node 已经可以看到master节点,notready是因为还未部署网络插件
[root@master1~]#kubectlgetnode
NAMESTATUSROLESAGEVERSION
master1NotReadymaster3m9sv1.14.1
查看所有的pod,kubectl get pod --all-namespaces
coredns也依赖于容器网络,此时pending是正常的
[root@master1~]#kubectlgetpod--all-namespaces
NAMESPACENAMEREADYSTATUSRESTARTSAGE
kube-systemcoredns-fb8b8dccf-8wdn80/1Pending02m21s
kube-systemcoredns-fb8b8dccf-rsnr60/1Pending02m21s
kube-systemetcd-master11/1Running089s
kube-systemkube-apiserver-master11/1Running094s
kube-systemkube-controller-manager-master11/1Running089s
kube-systemkube-proxy-9nl4m1/1Running02m21s
kube-systemkube-scheduler-master11/1Running0106s
配置KUBECONFIG变量
echo"export KUBECONFIG=/etc/kubernetes/admin.conf">> /etc/profile
source/etc/profile
echo$KUBECONFIG#应该返回/etc/kubernetes/admin.conf
5. 部署flannel网络
k8s支持多种网络方案,flannel,calico,openvswitch
此处选择flannel。 在熟悉了k8s部署后,可以尝试其他网络方案,我另外一篇1.9部署中有介绍flannel和calico的方案,以及切换时需要的动作。
kubectlcreate-fkube-flannel.yml
网络就绪后,节点的状态会变为ready
[root@master1~]#kubectlgetnode
NAMESTATUSROLESAGEVERSION
master1Readymaster11mv1.14.1
6. kubeadm join 加入node节点
6.1 node节点加入集群
使用之前kubeadm init 生产的join命令,加入成功后,回到master节点查看是否成功
[root@node1~]#kubeadmjoin192.168.4.130:6443--token911xit.xkp2gfxbvf5wuqz7\
>--discovery-token-ca-cert-hashsha256:23db3094dc9ae1335b25692717c40e24b1041975f6a43da9f43568f8d0dbac72
[root@master1~]#kubectlgetnode
NAMESTATUSROLESAGEVERSION
master1Readymaster12mv1.14.1
node1Ready9m52sv1.14.1
至此,集群已经部署完成。
6.2 如果出现x509这个报错
此处未更新,沿用1.12
如果有报错才需要做这一步,不然不需要。
这是因为master节点缺少KUBECONFIG变量
[discovery]Failedtorequestclusterinfo,willtryagain: [Gethttps://192.168.1.181:6443/api/v1/namespaces/kube-public/configmaps/cluster-info: x509: certificate has expired or is not yet valid]
master节点执行
exportKUBECONFIG=$HOME/.kube/config
node节点kubeadm reset 再join
kubeadmreset
kubeadmjoinxxx...
6.3 如果忘了join命令,加入节点方法
此处未更新,沿用1.12
若node已经成功加入,忽略这一步。
使用场景:忘了保存上面kubeadm init生产的join命令,可按照下面的方法加入node节点。
首先master节点获取token,如果token list内容为空,则kubeadm token create创建一个,记录下token数据
[root@master1kubernetes1.10]#kubeadmtokenlist
TOKENTTLEXPIRESUSAGESDESCRIPTIONEXTRAGROUPS
wct45y.tq23fogetd7rp3ck22h2018-04-26T21:38:57+08:00authentication,signingThedefaultbootstraptokengeneratedby'kubeadm init'.system:bootstrappers:kubeadm:default-node-token
node节点执行如下,把token部分进行替换
kubeadmjoin--tokenwct45y.tq23fogetd7rp3ck192.168.1.181:6443--discovery-token-unsafe-skip-ca-verification
7. 部署k8s ui界面,dashboard
dashboard是官方的k8s 管理界面,可以查看应用信息及发布应用。dashboard的语言是根据浏览器的语言自己识别的
官方默认的dashboard为https方式,如果用chrome访问会拒绝。本次部署做了修改,方便使用,使用了http方式,用chrome访问正常。
修改方法可以查看我简书中另一篇文档,修改dashboard 为http方式
一共需要导入3个yaml文件
文件地址 https://github.com/cai11745/k8s-ocp-yaml/tree/master/yaml-file/dashboard-1.10.1
kubectlapply-fkubernetes-dashboard.yaml
kubectlapply-fadmin-role.yaml
kubectlapply-fkubernetes-dashboard-admin.rbac.yaml
[root@master1~]#kubectl-nkube-systemgetsvc
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
kube-dnsClusterIP10.96.0.10<none>53/UDP,53/TCP,9153/TCP32m
kubernetes-dashboardNodePort10.97.8.30<none>443:32001/TCP,80:32000/TCP13m
创建完成后,通过 http://任意节点的IP:32000即可访问ui 不需要输入token,也不需要https
8. EFK和监控
方案github可查,监控推荐使用coreos的 prometheus,部署完成后通过grafana的nodeport访问,自带的模板已经满足日常使用。
9. FAQ
9.1 kubectl 命令补全
root@master1:/# vim /etc/profilecd #添加下面这句,再source
source<(kubectlcompletionbash)
root@master1:/# source /etc/profile
9.2 master节点默认不可部署pod
执行如下,node-role.kubernetes.io/master 可以在 kubectl edit node master1中taint配置参数下查到
root@master1:/var/lib/kubelet# kubectl taint node master1 node-role.kubernetes.io/master-
node"master1"untainted
9.3 node节点pod无法启动/节点删除网络重置
node1之前反复添加过,添加之前需要清除下网络
root@master1:/var/lib/kubelet# kubectl get po -o wide
NAMEREADYSTATUSRESTARTSAGEIPNODE
nginx-8586cf59-6zw9k1/1Running09m10.244.3.3node2
nginx-8586cf59-jk5pc0/1ContainerCreating09m<none>node1
nginx-8586cf59-vm9h40/1ContainerCreating09m<none>node1
nginx-8586cf59-zjb841/1Running09m10.244.3.2node2
root@node1:~# journalctl -u kubelet
failed:rpcerror:code=Unknowndesc=NetworkPlugincnifailedtosetuppod"nginx-8586cf59-rm4sh_default"network:failedtosetbridgeaddr:"cni0"alreadyhasanIPaddressdifferentfrom10.244.2.1/24
12252cni.go:227]Errorwhileaddingtocninetwork:failedtosetbridgeaddr:"cni0"already
重置kubernetes服务,重置网络。删除网络配置,link
kubeadmreset
systemctlstopkubelet
systemctlstopdocker
rm-rf/var/lib/cni/
rm-rf/var/lib/kubelet/*
rm -rf /etc/cni/
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1
systemctl start docker
加入节点 systemctl start docker
kubeadmjoin--token55c2c6.2a4bde1bc73a6562192.168.1.144:6443--discovery-token-ca-cert-hashsha256:0fdf8cfc6fecc18fded38649a4d9a81d043bf0e4bf57341239250dcc62d2c832
4 使用dashboard 部署tomcat集群
32000端口==》工作负载==》新建==》创建应用==》
5 k8s使用yml部署应用
5.1 deployment和service文件说明
deployment文件说明了部署的副本信息
service用于通知kube-proxy对外暴露的端口,只有启用了service文件,服务才可以被正确使用
5.2 部署tomcat应用
tomcat Dployment文件如下
apiVersion: extensions/v1beta1` --固定写法
`kind: Deployment` --标识是部署文件
`metadata:`
`name: tomcat-deploy` -- 生成的pod名字会在后面加上序列号进行区分
`spec:`
`replicas: 2` -- 生成几个副本
`template:`
`metadata:`
`labels:`
`app: tomcat-cluster` -- 用于标识这个文件 ,在后面的service 中走对应
`spec:`
`containers:`
`- name: tomcat-cluster` --容器名字 一般和app标签对应
`image: tomcat` -- 需要拉取的镜像不可以随便写
`ports:`
`- containerPort: 8080` -- 内部端口,一般写容器默认的端口
5.2 tomcatservice文件对外暴露端口
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
labels:
app: tomcat-service
spec: --细节说明
type: NodePort --节点端口
selector: --选择器
app: tomcat-cluster --对应部署文件的
ports:
- port: 8000
targetPort: 8080
nodePort: 32500
5.3 上面的三个端口说明
5.3 测试负载均衡
<%=request.getLocalAddr()%>
curl at2:32500/web/a.jsp
5.5 部署tomcat带容器卷
tomcat-deployment文件
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat-deploy
spec:
replicas: 5
template:
metadata:
labels:
app: tomcat-cluster
spec:
volumes:
- name: code-war
hostPath:
path: /opt/moule/
containers:
- name: tomcat-cluster
image: tomcat
ports:
- containerPort: 8080
volumeMounts:
- name: code-war
mountPath: /usr/local/tomcat/webapps
tomcat-service文件
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
labels:
app: tomcat-service
spec:
selector:
app: tomcat-cluster
ports:
- port: 8000
targetPort: 8080
访问要使用 内部ip ,宿主机的文件需要每个node节点都有
5.6 部署springboot项目
5.6.1创建自定义镜像
at2 服务器创建自定义镜像:
docker build -t dtsw-war /opt/shell/bsbdj/bsbdj/bsbdj-app/
## 5.6.2 推送到harbor上
docker tag dtsw-war at3:1180/library/dtsw-war
docker push at3:1180/library/dtsw-war
## 5.6.3 编写配置文件
apiVersion: v1
kind: Service
metadata:
name: dockertest
namespace: default
labels:
app: dockertest
spec:
type: NodePort
ports:
- port: 8000
targetPort: 8080
nodePort: 30900 #service对外开放端口
selector:
app: dockertest
--- 部署文件
apiVersion: extensions/v1beta1
kind: Deployment #对象类型
metadata:
name: dockertest #名称
labels:
app: dockertest #标注
spec:
replicas: 2 #运行容器的副本数,修改这里可以快速修改分布式节点数量
selector:
matchLabels:
app: dockertest
template:
metadata:
labels:
app: dockertest
spec:
volumes:
- name: code-war
运行kubectl delete -f dockertest.yaml可以删除pods与service 修改dockertest.ymal 中replicas数量后,运行kubectl apply -f dockertest.yaml可以扩容或收缩副本数量
6 部署docker本地镜像harbor
6.1、介绍
Docker容器应用的开发和运行离不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境内的Registry也是非常必要的。Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。
6.2、下载地址:
https://github.com/goharbor/harbor/releases
sudo tar -xvf harbor-offline-installer-v1.9.3.tgz
解压后目录
6.3、修改配置:
修改配置文件harbor.yml
hostname: 192.168.124.128 (自己本机地址)
port: 1180 (自己定义端口号,记得不要使用80端口)
harbor_admin_password: 12345 (admin进入密码)
6.4、启动程序
第一步:启动准备文件,使用root权限运行,免得权限不够。
sudo ./prepare
第二步启动安装程序
sudo ./install.sh
启动成功显示如下:
6.5、访问页面
http://192.168.124.128:1180 (使用改地址访问) ,密码:12345,之前配置的。
6.6、新建项目:
6.7、上传本地镜像到项目测试:
第一步:创建镜像tag。
docker tag mysql:5.7 192.168.124.128:1180/library/mysql:5.7
第二步:上传镜像
docker push 192.168.124.128:1180/library/mysql:5.7
遇到问题:
(1):An image does not exist locally with the tag
wxp@ubuntu-128://etc/docker$ docker push 192.168.124.128:1180/gogbee_dev/jenkinsci/blueocean
The push refers to repository [192.168.124.128:1180/gogbee_dev/jenkinsci/blueocean]
An image does not exist locally with the tag: 192.168.124.128:1180/gogbee_dev/jenkinsci/blueocean
解决办法,执行以下命令,创建标签:
docker tag jenkinsci/blueocean 192.168.124.128:1180/library/jenkinsci/blueocean
(2):http: server gave HTTP response to HTTPS client
wxp@ubuntu-129:~$ docker push 192.168.124.128:1180/library/graylog/graylog:3.0
Error response from daemon: Get https://192.168.124.128:1180/v2/: http: server gave HTTP response to HTTPS client
修改daemon.json
{
"insecure-registries":["192.168.124.128:1180"]
}
192.168.124.128:1180:ip和端口就是harbor配置的端口和ip。
重启docker 服务。
systemctl restart docker
(3):denied: requested access to the resource is denied (请求受到拒绝。)
wxp@ubuntu-128://etc/docker$ docker push 192.168.124.128:1180/goharbor/mysql:5.7
The push refers to repository [192.168.124.128:1180/goharbor/mysql]
8129a85b4056: Preparing
3c376267ac82: Preparing
fa9efdcb088a: Preparing
9e615ff77b4f: Preparing
e5de8ba20fae: Preparing
2bee3420217b: Waiting
904af8e2b2d5: Waiting
daf31ec3573d: Waiting
da4155a7d640: Waiting
3b7c5f5acc82: Waiting
295d6a056bfd: Waiting
denied: requested access to the resource is denied
解决办法:
使用docker登陆到harbor
wxp@ubuntu-128:/usr/local/share/ca-certificates$ docker login --username=admin 192.168.124.128:1180
Password:
--username=admin :harbor登录用户。
Password: 12345 (harbor设置密码。)
(4):Error saving credentials: error storing credentials - err: exit status 1, out: Cannot create an item in a locked collection
登录时报错,造成原因:是Ubuntu软件包的一个错误。
sudo apt-get remove golang-docker-credential-helpers
然后正常登录,这样就能推送成功,这样大功告成。
wxp@ubuntu-128:/usr/local/share/ca-certificates$ docker push 192.168.124.128:1180/library/mysql:5.7
The push refers to repository [192.168.124.128:1180/library/mysql]
8129a85b4056: Pushed
3c376267ac82: Pushed
fa9efdcb088a: Pushed
9e615ff77b4f: Pushed
e5de8ba20fae: Pushed
2bee3420217b: Pushed
904af8e2b2d5: Pushed
daf31ec3573d: Pushed
da4155a7d640: Pushed
3b7c5f5acc82: Pushed
295d6a056bfd: Pushed
5.7: digest: sha256:c0806ac73235043de2a6cb4738bb2f6a74f71d9c7aa0f19c8e7530fd6c299e75 size: 2617
查看harbor如下:
(5)received unexpected HTTP status: 500 Internal Server Error
df -h
查看磁盘信息,因为磁盘满了,导致没法上传镜像。
7 k8s常用命令
kubectl describe pod mytomcat-577fc9c556-2hhxj
查看pod 详细信息
kubectl get node --- 查看可以用 的节点
kubectl get node -o wide ===>查看集群详细信息
kubectl get deployment ==》 查看部署详情
root@node-1 k8s]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
查看容器
kubectl get pods
进入容器 (相当于 docker 进入容器)
kubectl exec -it mytomcat-577fc9c556-2hhxj /bin/bash
获取服务
kubectl get service
查看一个服务的详细情况
kubectl describe service tomcat-service
kubectl describe pod ==》 查看pod的详细情况
更新集群资源
kubectl apply -f yml
删除部署和服务
kubectl delete deployment | service
删除pod
delete pod nginx-deploy-78874bddbf-wbtxv
systemctl status kubelet 查看k8s状态
systemctl start kubelet 启动k8s
systemctl enable kubelet 开机自动启动k8s
kubectl describe service tomcat-service
kubectl get svc | grep gemfield-mysql 获取service简写
kubectl delete nodes k8s03 删除node节点
kubectl logs -f dockertest-86898764f9-h8tgg 【查看pod的日志】
kubectl delete -f dockertest.yaml可以删除pods与service
kubectl apply -f dockertest.yaml