前言
目前来看kubespray没那么成熟(2019/03/19)。
调研过很多部署工具,第三方得,官方得都试过。最终还是选择了kubespray,只因为它是官方工具,以及使用成熟得ansible方式。ansible是一个好工具。基于kubeadm,将kubernetes组件部署到容器上。
已测试4节点部署,一个master,三个node
kubernets版本:v1.13.4
本文章基于master分支: 3c4cbf133e76723fc0f360d15433795b08101e67
commit 3c4cbf133e76723fc0f360d15433795b08101e67
Author: Manuel Cintron <[email protected]>
Date: Wed Mar 13 15:58:25 2019 -0500
Adding ability to override dashboard replica count (#4344)
分享另外一个工具rancher,简单到令人发指:
https://rancher.com/docs/rancher/v2.x/en/quick-start-guide/deployment/quickstart-manual-setup/#2-install-rancher
环境准备
整体介绍
使用vmware虚拟机作为测试环境。每台虚拟机添加3张网卡,2张nat,一张host-only,实际上没用到多余得2张网卡,这里只是冗余配置。
全程使用root权限。
镜像使用CentOS-7-x86_64-Minimal-1708.iso。
虚拟机配置及功能介绍:
- master
控制节点。部署节点。
1核,2G内存,50G存储
网卡一:nat模式,10.10.10.210 - node01
计算,数据库(etcd)。
1核,2G内存,50G存储
网卡一:nat模式,10.10.10.211 - node02
计算,数据库(etcd)。
1核,2G内存,50G存储
网卡一:nat模式,10.10.10.212 - node03
计算,数据库(etcd)。
1核,2G内存,50G存储
网卡一:nat模式,10.10.10.213
基础环境配置
1. 加速源配置(每台机器均执行)
yum源
yum install -y wget
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache
pip源
mkdir ~/.pip
cat > ~/.pip/pip.conf << EOF
[global]
trusted-host=mirrors.aliyun.com
index-url=https://mirrors.aliyun.com/pypi/simple/
EOF
docker源
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://jzngeu7d.mirror.aliyuncs.com"]
}
EOF
2. 防火墙配置(每台机器均执行)
关闭firewalld
systemctl disable firewalld
systemctl stop firewalld
开启iptables
yum install iptables -y
yum install iptables-services -y
systemctl start iptables.service
systemctl enable iptables.service
iptables -F
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
service iptables save
systemctl restart iptables.service
3. 配置ip转发(每台机器均执行)
modprobe br_netfilter
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
sysctl -w net.ipv4.ip_forward=1
4. 安装docker(每台机器均执行)
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
yum install docker-ce-18.09.3 -y
systemctl enable docker
systemctl restart docker
5. 准备部署节点环境(只在master执行)
安装基础软件
yum install -y epel-release ansible git gcc openssl-devel
yum install -y python36 python36-devel python36-pip
配置免密登陆
配置主机解析:
vi /etc/hosts
添加如下内容
10.10.10.210 master
10.10.10.211 node01
10.10.10.212 node02
10.10.10.213 node03
生成ssh公私钥
ssh-keygen
拷贝公钥到目的机器,注意输入密码
ssh-copy-id -i /root/.ssh/id_rsa.pub root@master
ssh-copy-id -i /root/.ssh/id_rsa.pub root@node01
ssh-copy-id -i /root/.ssh/id_rsa.pub root@node02
ssh-copy-id -i /root/.ssh/id_rsa.pub root@node03
准备kubespray
下载:
git clone https://github.com/kubernetes-incubator/kubespray.git /etc/kubespray
安装依赖:
pip3.6 install -r /etc/kubespray/requirements.txt
pip3.6 install -r /etc/kubespray/contrib/inventory_builder/test-requirements.txt
pip3.6 install ruamel.yaml
生成配置文件:
cp -r /etc/kubespray/inventory/sample /opt/node
declare -a IPS=(10.10.10.210 10.10.10.211 10.10.10.212 10.10.10.213)
CONFIG_FILE=/opt/node/hosts.ini
python36 /etc/kubespray/contrib/inventory_builder/inventory.py ${IPS[@]}
替换被墙得源:
find /etc/kubespray -name '*.yml' | xargs -n1 -I{} sed -i "s/gcr\.io\/google_containers/gcr\.mirrors\.ustc\.edu\.cn\/google-containers/g" {}
find /etc/kubespray -name '*.yml' | xargs -n1 -I{} sed -i "s/gcr\.io\/google-containers/gcr\.mirrors\.ustc\.edu\.cn\/google-containers/g" {}
find /etc/kubespray -name '*.yml' | xargs -n1 -I{} sed -i 's/quay\.io/quay-mirror\.qiniu\.com/' {}
开始部署
编辑集群配置文件
vi /opt/node/hosts.ini
[kube-master]
master
[etcd]
node01
node02
node03
[kube-node]
node01
node02
node03
[k8s-cluster:children]
kube-master
kube-node
换源:vi /opt/node/group_vars/k8s-cluster/k8s-cluster.yml
kube_image_repo: "gcr.azk8s.cn/google-containers"
开启ingress:vim /opt/node/group_vars/k8s-cluster/addons.yml
ingress_nginx_enabled: true
部署(在master节点上执行)
ansible-playbook -i /opt/node/hosts.ini --become --become-user=root /etc/kubespray/cluster.yml
当 [file download], storage.googleapis.com 无法访问而失败时。多执行几次,这个网址是可以访问得,只是速度很慢,导致ansible部署超时。还未找到合适得替换源。
部署完成后,查看集群:
kubectl get nodes
至此部署结束。
使用
1. etcd状态查询
在部署了etcd得节点执行:
export ETCDCTL_API=3
etcdctl member list \
--endpoints=10.10.10.211:2379,10.10.10.212:2379,10.10.10.213:2379 \
--cacert /etc/pki/tls/certs/ca-bundle.crt \
--cert /etc/ssl/etcd/ssl/ca.pem \
--key /etc/ssl/etcd/ssl/ca-key.pem
2. kubernetes简单使用。
结构简单介绍
宏观介绍两层结构:构建服务 -- 发布服务
构建服务
k8s将一组互相关联得容器放在一个pod上,由pod暴露端口提供基础服务。
k8s提供deployment概念用于构建pod。
发布服务
发布服务就是让别人访问我们得pod。这里得“别人”可以是集群内部,也可以是集群外得网络。
k8s提供service概念用于发布服务。
service主要包含4种:
- ClusterIP:默认方式,只有集群节点内可以访问。
- NodePort:外部可以通过节点真实ip访问。
- LoadBalancer:通过负载提供一个外部访问点。需要和云平台集成。
- ExternalName:外部可以通过域名访问。比如 foo.bar.example.com。这里不介绍这种
启动一个简单但齐全得应用(master节点执行)
- 构建基础服务 -- deployment
这里演示两个容器组成的一个3副本pod。由于通过pod暴露端口,因此同一个pod内的容器不能使用相同的端口。
创建deployment yml文件:vim k1_deployment.yaml
添加如下内容:
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1
kind: Deployment
metadata:
name: nginx-rabbitmq-deployment # deployment 名称
spec:
replicas: 3 # pod 副本数
template:
metadata:
labels: # 标签,service在与pod关联时使用此值
app: nginx-rabbitmq # 标签键值对
spec:
containers:
- name: nginx # 容器名称
image: nginx:1.7.9 # 容器镜像
ports: # 容器端口,在这里也说成pod端口
- containerPort: 80
- name: rabbitmq
image: rabbitmq:3-management
ports:
- containerPort: 5671
- containerPort: 5672
- containerPort: 15671
- containerPort: 15672
env: # 容器环境变量
- name: RABBITMQ_DEFAULT_USER
value: user
- name: RABBITMQ_DEFAULT_PASS
value: password
创建 deployment:kubectl create -f k1_deployment.yaml
查看deployment:kubectl get deployments
查看deployment创建的pods:kubectl get pods
此时需要拉取镜像,会耗费一定时间创建。
- 发布服务 -- service
这里使用NodePort类型。
创建service文件:vim k1_node_service.yml
添加如下内容:
kind: Service
apiVersion: v1
metadata:
name: nginx-rabbitmq-service-node
spec:
type: NodePort # service 类型,默认为ClusterIP
selector: # 与deployment对应的标签选择器
app: nginx-rabbitmq # 标签键值对
ports:
- name: nginx # 若存在多个端口时,要添加名称
protocol: TCP # 协议类型
targetPort: 80 # pod端口(容器端口)
port: 20000 # 集群内部映射端口,不填会随机。ClusterIP使用的端口。
nodePort: 30000 # 集群节点映射端口,默认范围30000-32767。NodePort使用的端口。
- name: rabbitmq5671
protocol: TCP
targetPort: 5671
port: 20001
nodePort: 30001
- name: rabbitmq5672
protocol: TCP
targetPort: 5672
port: 20002
nodePort: 30002
- name: rabbitmq15671
protocol: TCP
targetPort: 15671
port: 20003
nodePort: 30003
- name: rabbitmq15672
protocol: TCP
targetPort: 15672
port: 20004
nodePort: 30004
创建service:kubectl create -f k1_node_service.yml
查看service:kubectl get service
使用chrome测试访问:
浏览器地址填写任意集群节点的ip地址,我这里使用10.10.10.210。30000是nginx,30004是rabbitmq管理端口。
有兴趣的也可以通过ClusterIP地址访问,此类型地址只能在集群内部可以访问到。
比如:
curl 10.233.53.35:20000
UI
chrome浏览器访问如下地址:
此时我们还没有用户去登陆,需先创建用户。
在mster节点执行如下命令:
- 创建用户
创建用户yml文件:vim dashboard-adminuser.yml
添加如下内容:
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system
执行创建命令:kubectl create -f dashboard-adminuser.yml
- 绑定权限
创建绑定文件:vim dashboard-adminuser-binding.yml
添加如下内容:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kube-system
执行创建命令:kubectl create -f dashboard-adminuser-binding.yml
- 获取登陆令牌:
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
- 在登陆页面选择令牌,输入获得的令牌即可登陆。
3. kubernetes扩展使用
ingress
ingress一般用于http之类的代理。ingress实际上还是和nodePort类似,使用安装了ingress-controller的节点ip进行访问,未实现vip功能。
使用前面的nginx-rabbitmq deployment进行测试ingress。
1. nginx-rabbitmq-deployment
和前面一致
2. nginx-rabbitmq-service
这里使用ClusterIP类型。
创建service文件:vim k1_cluster_service.yaml
kind: Service
apiVersion: v1
metadata:
name: nginx-rabbitmq-service-cluster
spec:
type: ClusterIP
selector: # 与deployment对应的标签选择器
app: nginx-rabbitmq # 标签键值对
ports:
- name: nginx # 若存在多个端口时,要添加名称
protocol: TCP # 协议类型
targetPort: 80 # pod端口(容器端口)
port: 20000 # 集群内部映射端口,不填会随机
- name: rabbitmq5671
protocol: TCP
targetPort: 5671
port: 20001
- name: rabbitmq5672
protocol: TCP
targetPort: 5672
port: 20002
- name: rabbitmq15671
protocol: TCP
targetPort: 15671
port: 20003
- name: rabbitmq15672
protocol: TCP
targetPort: 15672
port: 20004
执行创建命令:kubectl create -f k1_cluster_service.yaml
3. nginx-rabbitmq-ingress
用于代理nginx 和rabbitmq管理页面
创建ingress文件:vim k1_ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-rabbitmq-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/add-base-url: "true"
spec:
rules:
- http:
paths:
- path: /testNginx
backend:
serviceName: nginx-rabbitmq-service-cluster
servicePort: 20000
- path: /testRabbitMQ
backend:
serviceName: nginx-rabbitmq-service-cluster
servicePort: 20004
执行创建命令:kubectl create -f k1_ingress.yml
查看ingress命令:kubectl get ingress
4. 访问ingress地址
在chrome浏览器输入安装了ingress-controller节点的ip以及对应path。
我这里的环境为:
- 10.10.10.211/testRabbitmq
-
10.10.10.211/testNginx
访问效果如下:
loadbalancer
负载一般用于ip代理。
使用节点的ip访问服务始终不是好办法。自带的loadbalancer需要与云平台集成。
集成得方式没有环境,暂无法测试。
现尝试,keepalived+NodePort方式。
1. nginx-rabbitmq-deployment
直接使用前面得,无需重复创建。
2. nginx-rabbitmq-service-node
直接使用前面创建得NodePort类型得service。
3. 部署keepalived
- 安装keepalived
我这里在master节点和node03两个节点上安装。
两个节点上均执行:
yum install -y curl gcc openssl-devel libnl3-devel net-snmp-devel
yum install -y keepalived
- 配置keepalived
将两个节点得配置文件做备份。
两个节点上均执行:mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
修改master节点得配置文件:vim /etc/keepalived/keepalived.conf
# global_defs中:
# smtp_server改为 127.0.0.1
# ----------
# vrrp_instance VI_1中:
# 1. interface改为与vip同一网段得网卡名称
# 2. 在virtual_ipaddress中填写想要得vip
# 3. 注意priority值为100,这是优先级,从节点得优先级要比主节点得小。
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.10.10.250
}
}
修改node03节点得配置文件:vim /etc/keepalived/keepalived.conf
# global_defs中:
# smtp_server改为 127.0.0.1
# ----------
# vrrp_instance VI_1中:
# 1. interface改为与vip同一网段得网卡名称
# 2. 在virtual_ipaddress中填写想要得vip
# 3. 注意priority值为100,这是优先级,从节点得优先级要比主节点得小。
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.10.10.250
}
}
- 启动keepalived(两个节点均执行)
systemctl start keepalived
systemctl enable keepalived
- 测试keepalived
在master节点ip a
可以看到,ens33网卡多了一个vip地址。
使用chrome浏览器输入vip+NodePort类型得端口即可访问服务。
测试vip漂移:
在master节点:systemctl stop keepalived
此时到node03节点ip a
可以看到,ens33网卡多了一个vip地址。
使用chrome浏览器输入vip+NodePort类型得端口访问服务。
持久化存储(volume)
存储方案很多,不再举例。
参考:https://kubernetes.io/docs/concepts/storage/volumes/
由于卷是单点使用,也就是只能某个节点使用,这会导致其它节点得pod无法创建成功,当然某些外部卷可以实现漂移,但是依然只能同时只挂载在一个节点上(听说最新得openstack cinder实现了卷共享挂载)。虽然实现了多副本功能,但是对于有状态得服务,这似乎不大有用。
个人经验,可能有误。
注意事项
1. externalIPs
此参数,类似于额外的clusterIP,外部不能访问到。不要将此字段和节点ip置为相同。
排错
通过journalctl -xe
可以看到集群日志。
容器输出到控制台的日志,都会以 *-json.log 的命名方式保存在 /var/lib/docker/containers/ 目录下。
使用
kubectl create -f 为创建
kubectl apply -f 为更新