Galaxy固定容器IP网路方案
背景
在推动业务上容器过程中,存在业务方框架(如Java的dubbo)对ip依赖较重,但框架改造周期较长的问题。为了解决这个问题,运维侧从网络层面固定容器IP的方式着手,引入了腾讯开源的Galaxy插件。这里对此插件的安装部署进行说明。
Galaxy架构概览
Galaxy网络方案主要包括两个模块:
- galaxy:以daemonset形式存在每个k8s集群的节点上,它通过判断pod annotation信息,来设定pod网络是用固定ip还是非固定ip
- galaxy-ipam:根据pod的生命周期,完成pod ip的分配、释放、已分配ip信息的记录等功能
配置部署
预备环境
已有K8S集群环境
组件名 | 版本 |
---|---|
kube各组件 | 1.16.4 |
docker | 19.03.5 |
Galaxy方案的落地,需要结合cni插件一起来完成。Galaxy支持多种cni插件,包括flannel、SRIOV、vlan等,这里我们选择vlan的方式。
因此,每个k8s集群节点上需要安装kubernete-cni
yum install -y kubernetes-cni
注意:
执行以上操作之后,由于kubernetes-cni依赖于kubelet,导致其自动安装了最新版本的kubelet,将我们原本1.16.4的kubelet覆盖,所以需要做以下回退操作:rpm -e kubelet --nodeps && yum install -y kubelet-1.16.4
镜像准备
部署过程中,Galaxy网络方案的两个模块都是以容器方式运行的,因此我们先定制镜像,推送到我们的私有容器仓库。我们在部署使用的时候,当时galaxy最新版是v1.0.2,这里也以此版本来进行部署说明。
1. 下载镜像
我们需要的是:tkestack/galaxy:v1.0.2
和tkestack/galaxy-ipam:v1.0.2
两个镜像。
由于国内下载速度感人,大家可以想办法用其他代理方式进行下载,这里就不多说了。
2. 定制镜像
下载的镜像时区并不是北京时间的,可以采用两种方式解决:
- 方法一:每次使用镜像时,在yaml加上挂载宿主机/etc/localtime的配置
- 方法二:直接修改原镜像中的/etc/localtime为/usr/share/zoneinfo/Asia/Shanghai,一劳永逸
个人倾向方法二,这里以galaxy:v1.0.2
镜像制作为例进行说明(假设,私用仓库地址为:myhub.example.com/op-base)。
修改时区的Dockerfile如下:
FROM tkestack/galaxy:v1.0.2RUN rm -f /etc/localtime \&& ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
在Dockerfile文件所在目录,执行build操作:
docker build -t myhub.example.com/op-base/galaxy:v1.0.2 .
将镜像推送到我们的私有Harbor仓库(推送需要账号权限,需先docker login):
docker push myhub.example.com/op-base/galaxy:v1.0.2
配置部署galaxy模块
在Galaxy项目https://github.com/tkestack/galaxy/tree/master/yaml
路径下有我们需要的yaml配置文件:
将其下载到有kubectl
的节点,但是这些yaml有些地方需要修改。
1 运行galaxy的daemonset
配置部署galaxy模块,使用的是galaxy.yaml,有两处需要修改
(1)修改镜像和启动参数
......imagePullSecrets:- name: myhubcontainers:- image: myhub.example.com/op-base/galaxy:v1.0.2command: ["/bin/sh"]# qcloud galaxy should run with --route-eni# args: ["-c", "cp -p /etc/galaxy/cni/00-galaxy.conf /etc/cni/net.d/; cp -p /opt/cni/galaxy/bin/galaxy-sdn /opt/cni/galaxy/bin/loopback /opt/cni/bin/; /usr/bin/galaxy --logtostderr=true --v=3 --route-eni"]# private-cloud should run without --route-eniargs: ["-c", "cp -p /etc/galaxy/cni/00-galaxy.conf /etc/cni/net.d/; cp -p /opt/cni/galaxy/bin/galaxy-sdn /opt/cni/galaxy/bin/loopback /opt/cni/bin/; /usr/bin/galaxy --logtostderr=true --v=3"]
......
说明:
- 修改image为我们自定义的镜像
myhub.example.com/op-base/galaxy:v1.0.2
- 指定从私有仓库拉取镜像所需的secrets:
imagePullSecrets
配置为name: myhub
(这里根据自己实际情况而定) - 部署环境为自建机房,不是腾讯云,所以这里启动参数使用不带
--route-eni
(2)修改galaxy的网络配置
我们的诉求是:在一个K8S集群上,pod需要既能配置不使用固定ip,也可以配置使用固定ip。
即,在加上指定annotation参数时才使用固定ip方式配置pod网络,默认情况下,不用固定ip。
因此,我们采用bridge+vlan的两种网络方式:
默认情况下,走bridge网络,不会固定网络ip;
当识别带有
......
apiVersion: v1
kind: ConfigMap
metadata:name: galaxy-etcnamespace: kube-system
data:# update network card name in "galaxy-k8s-vlan" and "galaxy-k8s-sriov" if necessary# update vf_num in "galaxy-k8s-sriov" according to demandgalaxy.json: |{"NetworkConf":[{"name":"tke-route-eni","type":"tke-route-eni","eni":"eth1","routeTable":1},{"name":"galaxy-flannel","type":"galaxy-flannel", "delegate":{"type":"galaxy-veth"},"subnetFile":"/run/flannel/subnet.env"},{"name":"galaxy-k8s-vlan","type":"galaxy-k8s-vlan", "device":"eth0"},{"name":"galaxy-k8s-sriov","type": "galaxy-k8s-sriov", "device": "eth1", "vf_num": 10}],"DefaultNetworks": ["my-bridge"],"ENIIPNetwork": "galaxy-k8s-vlan"}
......
说明:
DefaultNetworks
指定为使用bridge方式,这里取名为my-bridge
(这个名字需要跟服务器节点上cni配置中的bridge名一致)device
指定服务器的网卡名为eth0
(网卡名根据实际情况来修改)
除了上面两处修改外,别忘了添加cni的bridge配置
# cat /etc/cni/net.d/10-my-bridge.conf
{"cniVersion": "0.2.0","name": "my-bridge","type": "bridge","bridge": "cbr0","addIf": "eth0","isGateway": true, "ipMasq": false,"ipam": {"type": "host-local","ranges": [[{"subnet": "10.20.30.0/26" }]],"routes": [{ "dst": "0.0.0.0/0" }]}
}
最后,执行如下命令就可以将galaxy的daemonset运行起来:
kubectl apply -f galaxy.yaml
运行成功后,在集群节点上会发现:
/opt/cni/bin/
目录下多了galaxy-sdn
和loopback
两个二进制文件;/etc/cni/net.d/
目录下生成了一个00-galaxy.conf
配置文件,内容如下:
{"type": "galaxy-sdn","capabilities": {"portMappings": true},"cniVersion": "0.2.0"
}
注意:之所以将bridge配置文件10-my-bridge.conf取名为10-
前缀,是为了让其排在00-
前缀的00-galaxy.conf文件后面被加载,不然会出现奇怪的问题。
2 配置kubelet支持cni网络插件
在kubelet的启动脚本里加上--network-plugin=cni --cni-bin-dir=/opt/cni/bin/
参数,然后重启kubelet。
kubelet的完整启动脚本内容类似如下:
# /usr/lib/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/[Service]
ExecStart=/usr/bin/kubelet \--eviction-hard=memory.available<1024Mi,nodefs.available<10%,nodefs.inodesFree<5% \--system-reserved=cpu=1,memory=1G \--kube-reserved=cpu=1,memory=1G \--cgroups-per-qos=true \--address={{your_node_ip}} \--hostname-override={{your_node_ip}} \--cgroup-driver=systemd \--pod-infra-container-image=myhub.example.com/kubernetes/pause-amd64:3.1 \--experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.conf \--kubeconfig=/etc/kubernetes/kubelet.conf \--cert-dir=/etc/kubernetes/pki \--cluster-dns={{your_dns_ip}} \--cluster-domain={{your_domain_postfix}}. \--network-plugin=cni \--cni-bin-dir=/opt/cni/bin/ \--hairpin-mode=promiscuous-bridge \--fail-swap-on=false \--feature-gates=RotateKubeletServerCertificate=true,RotateKubeletClientCertificate=true \--rotate-certificates \--serialize-image-pulls=false \--max-pods=60 \--logtostderr=true \--v=2
Restart=always
StartLimitInterval=0
RestartSec=5[Install]
WantedBy=multi-user.target
配置部署galaxy-ipam模块
1. 配置floatingip-config
假设:
k8s节点所属ip网段为:10.10.100.0/24
容器可用ip范围为:10.11.128.1~10.11.135.253
容器ip所属网段为:10.11.128.0/21
容器的网关ip为:10.11.135.254
vlan的id为:1200
注:这些网络信息,实际通常需要网络组同事帮忙分配确定
以ConfigMap的方式配置,这里创建floatingip-config.yaml
配置文件,内容如下:
kind: ConfigMap
apiVersion: v1
metadata:name: floatingip-confignamespace: kube-system
data:floatingips: '[{"routableSubnet":"10.10.100.0/24","ips":["10.11.128.1~10.11.135.253"],"subnet":"10.11.128.0/21","gateway":"10.11.135.254","vlan":1200}]'
说明:
- routableSubnet:指定kubelet节点所在网段
- ips:指定为容器ip分配的地址范围
- subnet:容器ip的网段
- gateway:容器地址分配的网关
- vlan:是用来指定容器ip的vlan id,当容器ip和节点ip不属于同一个vlan时需要配置(id为数值类型,写的时候不要带引号)
floatingip-config.yaml
创建完后,执行以下命令生效:
kubectl apply -f floatingip-config.yaml
2 修改galaxy-ipam.yaml配置文件
(1)修改镜像
......imagePullSecrets:- name: myhubcontainers:- image: myhub.example.com/op-base/galaxy-ipam:v1.0.2
......
说明:
- 修改image为自定义镜像
myhub.example.com/op-base/galaxy-ipam:v1.0.2
- 指定从私有仓库拉取镜像所需的secrets:
imagePullSecrets
配置为name: myhub
(这里根据自己实际情况而定)
(2)修改galaxy-ipam-etc配置
......
apiVersion: v1
kind: ConfigMap
metadata:name: galaxy-ipam-etcnamespace: kube-system
data:# delete cloudProviderGrpcAddr if not ENIgalaxy-ipam.json: |{"schedule_plugin": {"storageDriver": "k8s-crd","cloudProviderGrpcAddr": "127.0.0.2:80" # 删除此行}}
......
说明:
- 由于我们是自建IDC环境,删除
"cloudProviderGrpcAddr": "127.0.0.2:80"
此行配置
修改完后,执行以下命令生效:
kubectl apply -f galaxy-ipam.yaml
3 配置kube-scheduler
(1)首先配置scheduler-policy.yaml
:
# make sue --policy-configmap=scheduler-policy of kube-scheduler is set
# note that --policy-config-file and --use-legacy-policy-config is conflict with --policy-configmap
apiVersion: v1
kind: ConfigMap
metadata:name: scheduler-policynamespace: kube-system
data:# set "ignoredByScheduler" to true if not ENIpolicy.cfg: |{"kind": "Policy","apiVersion": "v1","extenders": [{"urlPrefix": "http://10.20.30.40:9040/v1","httpTimeout": 70000000000,"filterVerb": "filter","BindVerb": "bind","weight": 1,"enableHttps": false,"managedResources": [{"name": "tke.cloud.tencent.com/eni-ip","ignoredByScheduler": true}]}]}
说明:
urlPrefix
这里指定的地址是galaxy-ipam的svc的CLUSTER-IP(可以通过kubectl get svc -n kube-system
查看)ignoredByScheduler
的说明是这样的If you want to limit each node's max Float IPs, please set ignoredByScheduler to false, then the Float IP resource will be judge by scheduler's PodFitsResource algorithm.
。这里没有太理解它的意思,由于我们是自建IDC环境,按照注释提示,应该设为true
(2)配置kube-scheduler的启动脚本
在kube-scheduler的启动脚本里添加参数:--policy-configmap=scheduler-policy
,然后重启kube-scheduler
注意:要确保kube-scheduler有访问configmap的权限,否则会有类似如下的报错:
为system:kube-scheduler
添加configmaps权限最直接的方法就是执行如下命令进入编辑:
kubectl edit clusterrole system:kube-scheduler -o yaml
然后添加:
- apiGroups:- ""resources:- configmapsverbs:- get- list- watch- update- create- patch
之后再查看已经有了configmaps权限:
kubectl describe clusterrole system:kube-scheduler
这时再执行systemctl restart kube-scheduler
重启即可。
如何让pod配置使用固定ip
当galaxy和galaxy-ipam模块按上述步骤配置完成后,配置一个示例验证一下固定ip的功能是否实现
创建一个test-busybox.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:name: test-busybox
spec:replicas: 3selector:matchLabels:name: test-busyboxtemplate:metadata:labels:tag: lxcfsname: test-busyboxannotations:k8s.v1.cni.cncf.io/networks: "galaxy-k8s-vlan"k8s.v1.cni.galaxy.io/release-policy: "never"spec:tolerations:- operator: "Exists"containers:- name: test-busyboximage: busyboxcommand:- sleep- "3600"resources:requests:cpu: "0.1"memory: "32Mi"tke.cloud.tencent.com/eni-ip: "1"limits:cpu: "0.1"memory: "32Mi"tke.cloud.tencent.com/eni-ip: "1"
说明:
annotations配置:
k8s.v1.cni.cncf.io/networks: "galaxy-k8s-vlan"
:指明使用的网络类型为galaxy-k8s-vlan
k8s.v1.cni.galaxy.io/release-policy: "never"
:指明ip的释放策略,有never
和immutable
两种never
: Never Release IP even if the Deployment or Statefulset is deleted. Submitting a same name Deployment or Statefulset will reuse previous reserved IPs.immutable
: Release IP Only when deleting or scaling down Deployment or Statefulset. If POD float onto a new node in case of original Node became NotReady, it will get the previous IP.
注: 在跟galaxy开发者交流时,他建议使用
never
参数,immutable
可能在后面的迭代中被废弃掉。resources配置:
requests
和limits
属性都要添加tke.cloud.tencent.com/eni-ip: "1"
不配置的话,会报如下错误:
fail to establish network map[]:neither ipInfo from cni args nor ipam type from netconf
通过删除一个正在Running的pod,然后会发现再被创建出来的pod使用的ip和被删除时的ip一样,这便达到了我们固定ip的目的。
v1.0.2版本galaxy存在的问题
经过我们实际使用测试,发现v1.0.2版本存在两个问题:
- 多vlan支持: 当有多个vlan时,一个vlan中的ip分配完之后,不会自动分配下一个vlan的ip,而是pending
- svc问题:启用了固定ip的pod访问集群任意的svc地址都不通
对于第一个问题,我们使用一个vlan,然后在交换机层面用vxlan来隔离来避开了。
对于第二个问题,由于我们业务应用暂时没有访问svc的场景,所以也暂时不影响使用。
目前,galaxy已更新到了v1.0.3版本,新版本中已经解决了上述两个问题。
Galaxy固定容器IP网路方案相关推荐
- docker-compose 固定容器IP地址
写在前面 构建微服务的时候需要固定容器的ip,防止后期重启后ip变动. 本来说在portainer里面固定的ip,虽然效果挺好的,但是还是想写在docker-compose里面. 这里提供两种方法固定 ...
- (五)Docker查看容器ip及指定固定IP
如不懂Docker的网络模式及网络配置的请查看Docker四种网络模式和Docker网络配置 一.Docker如何查看容器ip docker inspect <container-ID> ...
- 固定docker容器IP方法
docker 默认有4种网络模式,详细可查看我曾经写的 "docker几种网络模式" docker run 新建并启动容器时,不指定网络,默认是使用桥接模式,容器内部IP是通过DH ...
- docker容器的网络配置,允许docker可以被宿主机以外的其它主机访问以及局域网内可以直接访问docker容器ip
自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求.容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信. 一.端口映射(局域网,外网 ...
- Nginx容器日志收集方案fluentd+elasticsearch+kilbana
容器技术在发展到今天已经是相当的成熟,但容器不同于虚拟机,我们在使用容器的同时也有很多相关的技术问题需要解决,比如:容器性能监控,数据持久化,日志监控与分析等.我们不能像平时使用虚拟机一样来管理容器, ...
- Nginx容器动态流量管理方案-nginx-upsync-module+nginx_upstream_check_module初体验
缘起 最近一直在研究日志收集系统的框架,之前在线游戏的数据发送都是由游戏服务器发送的,我来之前一直是rsync传输,也还算稳定.但现在上了单机游戏,只能由手机客户端直接发送,dau比较高,最近很火的& ...
- docker 创建容器时指定容器ip
docker 创建容器时指定容器ip Docker创建容器时默认采用bridge网络,自行分配ip,不允许自己指定. 在实际部署中,我们需要指定容器ip,不允许其自行分配ip,尤其是搭建集群时,固定i ...
- docker容器IP的设置
Docker创建容器时默认采用bridge网络,自行分配ip,不允许自己指定.在实际部署中,我们需要指定容器ip,不允许其自行分配ip,尤其是搭建集群时,固定ip是必须的.我们可以创建自己的bridg ...
- win10固定本机IP地址方案总结
win10固定本机IP地址方案总结 1.需求背景 作为程序开发人员来说,在一些特定的时候需要固定本地的IP地址,比如暴露自己IP地址的时候不用每次都去查询. 2.解决方案 无论是无线网还是以太网,其操 ...
最新文章
- 连接ORACLE实例
- 中国牡蛎碳酸钙市场需求现状调研及十四五投资风险评估报告2022-2028年版
- linux shell 等待输入_linux运维——基础篇
- 「项目已被 macOS 使用,不能打开」的处理办法
- IOS学习笔记之 Socket 编程
- mysql下载备份数据库命令行_MYSQL 数据库导入导出命令 | 很文博客
- Java并发包的理解
- Maxscript开发笔记
- PHP内容管理系统详细制作步骤
- 【一句日历】2019年9月
- 101. 熟悉 Java 并发吗,谈谈对 JUC 线程池 ThreadPoolExecutor 的认识吧
- ttl低电平接大电阻_电压不稳定?那是你不懂上拉/下拉电阻原理,5分钟教你应用!...
- UE4 Spline的使用
- 中金财富后台开发一面经验分享
- ElasticSeach详细安装教程--图文介绍超详细
- 美团专家:35岁是程序员的终点?
- 最新版Visual Studio Code下载及远程连接服务器(很详细哦)
- 【常见问题】Waki_谢老师B站的HCNP/HCIP课程第27集的华为eNSP路由器配置问题——百兆口不能添加IP地址
- 【转载】关于 .Net 逆向的那些工具:反编译篇
- hdu4525威威猫系列故事——吃鸡腿