CentOs我实在用不惯,也没有ubuntu用的熟悉,虽然网上中文k8s上基本都是CentOS的安装教程,甚至Kuboard官网上也是用CnetOs,我也试着跟着搭建,但是却是无法成功,我也很无奈,所以用ubuntu来安装
1.ubuntu18.04.2和k8s的版本是1.15.0的(dockerhub上已经有1.15.3了)
2.三个虚拟机
----k8s-master(主节点主机名)
----k8s-node1(子节点主机名)
----k8s-node2(子节点主机名)
3.dockerHub的账户以及对应的镜像仓库(有对应的k8s的1.15.0配置的镜像7个),最好先pull到虚拟机以免初始化的时候去pull消耗时间,当然了也可以自己搭建本地私有仓库,是同样的道理,只是需要把登陆的用户名和密码通过k8s名称生成secret,配置在yaml里,这样就能通过secret直接取仓库pull镜像了,否则就需要虚拟机保持仓库的登陆状态才能pull镜像
由于k8s和docker是有版本兼容问题的,目前v1.15.0需要docker版本18.06.x-ce,这里我选择是18.06.1ce3-0~ubuntu
由于apt官方库里的docker版本可能比较旧,所以先卸载可能存在的旧版本:
$ sudo apt-get remove docker docker-engine docker-ce docker.io
更新apt包索引:
$ sudo apt-get update
安装以下包以使apt可以通过HTTPS使用存储库(repository):
$ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
添加Docker官方的GPG密钥:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
使用下面的命令来设置stable存储库:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
再更新一下apt包索引:
$ sudo apt-get update
列出可用的版本:
$ apt-cache madison docker-ce
开始安装
sudo apt-get install docker-ce=18.06.1~ce~3-0~ubuntu
重新加载配置信息并设置自启动,重启服务
systemctl daemon-reload
systemctl enable docker && systemctl restart docker
修改或创建/etc/docker/daemon.json,镜像库和docker驱动设置:
#复制下面的内容执行即可
cat >/etc/docker/daemon.json <
解决docker info出现的警告(可以不理会)
docker info 警告"WARNING: No swap limit support"
vim /etc/default/grub
找到 GRUB_CMDLINE_LINUX=""
在双引号里面输入cgroup_enable=memory swapaccount=1
然后执行: sudo update-grub
reboot 搞定。
添加相应的源下载kubeadm和kubelet和kubernetes-cni,多以需要添加源,国外的直接添加google源,具体可以网上搜索。国内的推荐中科大的源,命令如下:
cat < /etc/apt/sources.list.d/kubernetes.list
deb http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial main
EOF
如果上面中科大的源出现了问题,可以使用阿里的源:https://mirrors.aliyun.com/kubernetes/apt/
有可能会出现如下情况:
注意:需要添加如上的源才能下载对应kubernetes的组件的版本,而且一旦加上就会导致apt-get update的时候就会出现下面的问题,我实际出现的后8位是BA07F4FB
添加源之后,使用 apt-get update 命令会出现错误,原因是缺少相应的key,可以通过下面命令添加(E084DAB9 为上面报错的key后8位):
gpg --keyserver keyserver.ubuntu.com --recv-keys BA07F4FB
gpg --export --armor BA07F4FB | sudo apt-key add -
配置网络设置等信息(所有节点)
cat < /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
运行如下命令使上面设置生效
sysctl --system
关闭sellinux(所有节点)
—(ubuntu18.04.2好像默认是关闭的,查询的时候就是disable)
apt-get install selinux-utils
安装 selinux-utils才能运行如下命令
getenforce
查看selinux状态,点击滚轮粘贴
setenforce 0
临时关闭selinux(所有节点)
关闭swap(所有节点)----必须这样(不然kubelet会出问题,k8s无法安装成功)
(1)临时关闭swap分区, 重启失效;
swapoff -a
(2)永久关闭swap分区(实测只执行还没有吧swap关闭,不知道有用没有)
sed -ri 's/.*swap.*/#&/' /etc/fstab
最好也这样改一下吧
vi /etc/fstab
注释掉swap那一行
#UUID=7dac6afd-57ad-432c-8736-5a3ba67340ad swap swap defaults 0 0
查看swap使用,如果swap是0说明关闭了
free -m
#加载br_netfilter(可有可无)
modprobe br_netfilter
安装kubeadm kubelet kubectl kubernetes-cni
sudo apt-get install -y kubelet=1.15.0-00 kubeadm=1.15.0-00 kubectl=1.15.0-00 kubernetes-cni=0.7.5-00
安装完成后,最好和docker一样设置kubelet为开机启动,systemctl(ubuntu16才有)也就是
systemctl enable kubelet && systemctl start kubelet
去下面的文件更改内容(免得后面错)—(子节点配置,主节点不配置好像也是没问题的,不过最好配置上)
vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
子节点需要配置这两个,一个是和docker一样的cgroup-driver这里的–cgroup-driver=systemd就和上面的/etc/docker/daemon.json里的对应了,一个是连接网络插件的配置,不配置这个将导致子节点无法找到network,而导致节点NoReady
事实上,子节点仅仅只需要配置如下内容和安装kubelet和kubeadm就可以了,当然还有docker
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml --cgroup-driver=systemd"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/ --cni-bin
注意这里有个小问题,就是如下配置是已经存在了,仅仅只需要在后面添加–cgroup-driver=systemd即可
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml
设置完成后wq保存后,需要运行如下命令重启kubelet
systemctl daemon-reload
systemctl restart kubelet
通过如下命令查询默认配置需要下载的镜像(注意用自己想要的版本)
kubeadm config images list
#通过自己修改默认配置创建的配置文件查看自己配合的镜像库k8s所需镜像,这里的kubeadm.yaml是自定义的文件,这里不做展开,因为会有插件安装的问题,因为它无法和–pod-network-cidr命令一起用.
目前我也没找到如何在配置这个参数方法,所以无法成功安装flannel插件和calico插件,我这里需要用flannel插件(好像kubernetes-dashboard默认需要flannel)
kubeadm config images list --config kubeadm.yaml
Ubuntu使用的查看kubeadm的默认配置信息copy改改(例如镜像库)就是自定义的yaml文件了
kubeadm config print join-defaults
kubeadm config print init-defaults
K8s默认支持多种网络插件如flannel、weave、calico,这里我们使用flanne,需要设置–pod-network-cidr参数,10.244.0.0/16是kube-flannel.yml文件配置的默认网段,如果需要修改,–pod-network-cidr和kube-flannel.yml文件需要保持一致。
–pod-network-cidr是指配置节点中的pod的可用IP地址,此为内部IP
这里一步是最容易出问题的,第一个可能就是你的虚拟机的核心不足2个,需要设置为2个以上,可以在Vmware里对应的虚拟机的设置里cup选项设置
172.16.171.xxx是你master节点的ip这里最好设置下,防止搭建多个master节点的时候,让k8s默认去选择,自己就可以指定,这样节点就能清晰知道自己是属于谁管了
marksmithbiao这个就是我dockerHub上的仓库名(命名空间)
–pod-network-cidr=10.244.0.0/16这个就是flannel需要在init设置的参数
–ignore-preflight-errors=Swap这个应该是排除swap,注意首字母大写
sudo kubeadm init --apiserver-advertise-address=172.16.171.xxx --image-repository=marksmithbiao --kubernetes-version=v1.15.0 --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=Swap
成功后如下:
这个命令是需要马上就执行的,否则是无法使用类似于kubectl get nodes这样查询命令的,这个是k8s授权你使用kubectl命令,具体的细节,可以搜索相关的资料:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
不执行如上命令将导致如下错误:(子节点使用kubectl会报此错也是这个原因)
The connection to the server localhost:8080 was refused - did you specify the right host or port?
还有一个主意点就是,那个kubeadm join --token …那串字符,是用来在子节点运行,添加子节点到集群里去的,那些token是有过期时间的,好像是一天,过期了就需要通过如下命令在master节点执行获取token:
#获取第一个token
kubeadm token create
#获取第二个token
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
#拼接命令
kubeadm join ip:port --token 第一个命令所得字符串(token) --discovery-token-ca-cert-hash sha256:第二个命令所得字符串(token)
当然了,这里先别去添加字节点到集群里去,这里master还没好,当你使用kubectl get nodes查询节点时,一般会发现master节点,其实就是一个节点,它是NoReady状态的,是无法工作的,你可以使用journalctl -f -u kubelet查看日志,会发现它会说没有cni的plugin插件(如下(盗图))
由于上面我初始化的时候配置了flannel的参数,所以这里选择安装flannel插件
执行命令
sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
使用kubectl get pods -n kube-system查看是否正常running,一般需要等一段时间,其中coredns的那两个,需要安装网络插件之后才会正常
事实上,一般只需要执行上面的命令即可,但是如果出现错误的话,可以再运行如下命令
sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml
卸载flannel就是把上面的apply改成delete即可,其他的yaml操作是同理
#第一步
sudo kubectl delete-f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#第二步,在node节点清理flannel网络留下的文件
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/
rm -f /etc/cni/net.d/*
注:执行完上面的操作,重启kubelet
你再运行kubectl get nodes一般都会running了
如果不想运行其他的子节点,可以把master也当成work节点来用,也就是在上面部署服务,就是让pod容忍master的污点,具体设置可以到网上查询:
kubectl taint nodes --all node-role.kubernetes.io/master-
如果你执行如上操作,记住需要给master足够的资源,否则重要的服务会挂掉,例如kube-controller-manager这样核心的功能,你用着用着就报错了(到时候就抓狂了,网上找不到对应的解法),还有就是你部署的服务如果过多的话,会出现驱逐pod的情况,具体可以根据自己的情况探索.
在子节点运行master节点init成功后的那个kubeadm join --token …,运行成功后,即可到master节点运行kubectl get nodes查看字节是否加入集群,如果你的子节点是NoReady状态,那么你需要去字节点使用
journalctl -f -u kubelet查看日志(-f是持续输出,-u是筛选过滤那些日志,这里是kubelet的),还有其它的命令可以自己去探索,一般来说都是之前说到的没有配置那个cni的配置,具体你根据日志分析原因.
1.Kuboard
Kuboard官网里有k8s安装等教程,安装使用都是详细的说明,很简单三五个命令即可使用
https://kuboard.cn/install/install-dashboard.html
2.kubernetes
我们重点来安装这个,k8s官方的(我这里的这个没有配置监控内存和cup等资源)
官方gitHub地址:
https://github.com/kubernetes/dashboard
这个是官方的安装方法
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
不过因为网络原因,是无法获取到对应的镜像的,需要下载文件修改镜像(点击如上的https链接即可),这些镜像在dockerHub有很多,我自己在dockerHub找了一个镜像替换了默认的镜像,具体如下:
siriuszg/kubernetes-dashboard-amd64就是dockerHub上的镜像,注意你需要替换完全,别漏了
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------- Dashboard Secret ------------------- #
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kube-system
type: Opaque
---
# ------------------- Dashboard Service Account ------------------- #
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
---
# ------------------- Dashboard Role & Role Binding ------------------- #
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
rules:
# Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
# Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create"]
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
verbs: ["get", "update", "delete"]
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system
---
# ------------------- Dashboard Deployment ------------------- #
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: siriuszg/kubernetes-dashboard-amd64
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
# ------------------- Dashboard Service ------------------- #
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
有时候kubernetes-dashboard会出问题,我们需要卸载重新安装,那么就用如下命令:
卸载kubernetes
sudo kubectl -n kube-system delete $(sudo kubectl -n kube-system get pod -o name | grep dashboard)
通过kubectl get service -n kube-system即可查询kubernetes-dashboard的外网访问地址,通过集群节点的ip加上:这里的30430即可访问,只有火狐能够访问,而且是https方式,因为需要无视证书去运行.
到这里k8s的安装就差不多了,你如果需要运行自己的服务,自己的代码到上面,就需要自己做镜像到你配置在k8s上的镜像库里,这样你通过对应yaml文件部署的时候,它就可以直接取仓库里pull你的镜像去跑服务了,具体访问,还有很多的东西,很难一时讲清楚.
忘了说了关于镜像仓库的用户名和密码的问题:
通过如下命令设置docker镜像仓库的访问的secret,这个secret可以配置在yaml里面,这样就不用再虚拟机里登陆docker login而就可以直接取pull在dockerHub上的镜像了,这里我还没有尝试过,我是虚拟机docker login登陆的.后面会去配置的:
kubectl create secret docker-registry registry-secret --docker-server=http://172.16.171.142:5000 --docker-username=xx --docker-password=xxx --docker-email=xxx@xxx --namespace=default
我们部署的服务如果需要外网去访问,就需要设置对应配置,常见的就是NodePort,不过生产环境只会暴露网管服务NodePort,这样就能保证该服务不被外网直接访问,而需要通过网关,而网关都是有鉴权授权等的.不过我们测试的话,可以暴露也没关系
一般可以直接写pod的yaml,这个最简单,也很方便,如下
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
#注意这里的版本号用冒号(:)隔开
image: nginx:1.7.9
#开放外网访问的端口(这个不需要service服务也能访问)
ports:
#这个是访问容器的端口,nginx默认是80,使用的是10.xxx的那个
- containerPort: 80
#这个是通过宿主机ip访问的端口
hostPort: 8080
imagePullPolicy: IfNotPresent
restartPolicy: Always
由于pod是生命周期是不稳定的,需要使用service来作为桥梁来访问pod,所以配置对应的service模块,来访问服务.其中标签里的type和project和server需要对应,最好都使用一样的,当然了实际也没有必要加这个多标签,至二级一个run标签这里也就够了:
kind为Service的是service服务,而下面kind是Deployment的是用来管理pod的,可以配置pod的副本等比kind更多配置的配置.都是配置pod的
其中,service通过selector选择器的标签lables来匹配pod,这样就能通过访问service来访问pod了,service里的targetPort需要对应pod的服务端口,更详细的说明,可以去网上官网等研究更细的配置:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
type: nginx
project: server
server: nginx-server
ports:
- protocol: TCP
port: 8889
targetPort: 80
#开启外网访问
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server
labels:
type: nginx
project: server
server: nginx-server
spec:
replicas: 1
selector:
matchLabels:
type: nginx
project: server
server: nginx-server
template:
metadata:
name: nginx-pod
labels:
type: nginx
project: server
server: nginx-server
spec:
containers:
- name: nginx-pod
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
#这里的registry-secret就是上面使用kubectl create secret xxxx生成的registry-secret
#imagePullSecrets:
#- name: registry-secret
restartPolicy: Always
1.通过kubectl get service可以看见对应的外网端口和内网端口(service可以简写为svc):
3开头的那个是外网访问地址,用任意一个节点的ip:3开头端口即可访问,内网访问可以直接用前面的那个10开头的内网地址:9999(内网端口)访问
下面这个是简化lables了的,只要一个run标签,道理是一样的,需要对应标签名,service才能匹配到pod
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
run: nginx-pod
ports:
- protocol: TCP
port: 8088
targetPort: 80
#type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pod
labels:
run: nginx-pod
spec:
replicas: 1
template:
metadata:
name: nginx-pod
labels:
run: nginx-pod
spec:
containers:
- name: nginx-pod
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
restartPolicy: Always
selector:
matchLabels:
run: nginx-pod
由于篇幅时间原因,我这里不贴出遇到的问题和对应的解决方法了,网上一般都搜索得到,当然了也可以留言和我交流,我如果遇到过或是知道,必然会给你解答.
花费很长时间写这个,主要是因为自己也确实踩了很久的坑,才勉强搭建好,更深层及的运维和原理需要后面慢慢学习.因为在网上的资料真的不那么好使,大多数过于简练,之前原本想先学会k3s和k3os,可是那个更是没法弄,因为根本就不知道怎么设置自己的镜像库.无法使用.
最主要的原因就是网上根本没有见到过直接在kubeadm init那里直接设置自定义仓库的,要么直接用自定义的kubeadm-config.yaml,要么直接使用kubeadm init,前者没有说明插件参数是怎么设置的,虽然可以使用自己的镜像库,但是安装常用网络插件无法安装成功,没有在init设置对应的插件参数,后者使用的默认的配置,镜像还是默认的谷歌的,虽然可以如网上所说的,去dockerHub进行pull下来改名称为谷歌的,但是你自己的服务的镜像呢,也这个搞吗?这个都是使用本地镜像,也就是没有去仓库pull,因为如果不是做不到的,网速怕是也是个问题.
所以我这里的使用kubeadm init是我的最佳实践,希望你能越过那些坑.
后来发现,直接在自定义的配置文件里设置好对应的网络插件ip范围,也可以安装成功的,如下是自定义的kubeadm-config.yaml配置,直接使用命令(纯手敲命令,可能会有错)
kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=Swap
apiServer:
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
#这个是阿里云的镜像库
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
networking:
dnsDomain: cluster.local
#这个就是flanne的ip范围
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
scheduler: {}