
- 前言
- (本书关注基于docker的生态系统搭建、运维、开发、测试)
- 如何搭建python(django/flask)、php、tomcat等docker的开发环境?
- 如何运用yum本地源、gitlab软件仓库、registry应用仓库、kubernetes完成CICD?
- 版本:
- KVM+CoreOS(1855.4, docker 18.06)
- 微信文章
- docker 基础
- 基本概念
- docker是什么?docker仓库是什么?
- 为了解决应用环境配置的难题,将一个个应用打包成镜相(image),存放这个镜相的地方称为docker仓库(registry),运行起来的实例称为容器(container)
- 站在 Docker 的角度,软件就是容器的组合:业务逻辑容器、数据库容器、储存容器、队列容器……Docker 使得软件可以拆分成若干个标准化容器,然后像搭积木一样组合起来。
![图片[1]-基于docker、K8S的CICD应用环境-效率工具论坛-资源-SpringForAll社区](https://spring4all.com/wp-content/themes/zibll/img/thumbnail-lg.svg)
- 如何使用?
- 通过一组docker命令来实现打包、运行、起动、停止、删除、上传、下载等一系列相关操作。
- 有何特性?
- package once, run anywhere.
- 安装
- 升级docker
- [root@docker ~]# yum install docker-ce
- 测试容器:
- docker run –name busybox -d busybox /bin/sh -c “while true; do sleep 1; done”
- docker exec -it busybox sh
- docker run –name dbtest -itd debian bash
- docker run –name ubtest -itd ubuntu bash
- 常用配置
- 镜像源为国内官方源以及内部仓库
- [root@docker ~]# vim /etc/docker/daemon.json
- “insecure-registries”: [ “192.168.31.140:5000″,”192.168.100.222:5000”]
- 或者通过修改/etc/default/docker
- DOCKER_OPTS=”–registry-mirror=https://registry.docker-cn.com”
- $DOCK_REG_IP=”192.168.31.140″
- #IP=`ip addr show dev eth0|grep -Po ‘inet \K\w*.\w*.\w*.\w*’`
- sed -i.ori “s#ExecStart=/usr/bin/dockerd#ExecStart=/usr/bin/dockerd –insecure-registry $DOCK_REG_IP:4000 –mtu 1400#” /usr/lib/systemd/system/docker.service
- 重启docker: systemctl restart docker
- 基本命令
- docker start/stop/logs/restart
- dockerfiile
- ubuntu jenkins example
- RUN echo ” > /etc/apt/sources.list.d/jessie-backports.list && \
- apt-get update && apt-get install -y git
- 使用supervisord示例
- Dockerfile
- RUN yum install epel-release -y
- RUN yum install nginx supervisor -y && yum clean all
- RUN sed -i ’47a proxy_pass http://127.0.0.1:9000;’ /etc/nginx/nginx.conf
- COPY supervisord.conf /etc/supervisord.conf
- ENV PATH /usr/local/jdk/bin:$PATH
- CMD [“/usr/bin/supervisord”]
- supervisord.conf
- command=/usr/local/jdk/bin/java -jar /tale/tale-least.jar
- command=/usr/sbin/nginx -g “daemon off;”
- docker-compose
- 升级docker-compose至指定版本
- chmod +x /usr/local/bin/docker-compose
- docker-compose.yml
- mkdir /opt/cmp_bind;cd /opt/cmp_bind;
- vi docker-compose.yml
- bind:
- – /opt/bind/entrypoint.sh:/sbin/entrypoint.sh
- 基本命令
- docker-compose start/stop/rm/restart/logs
- docker registry
- registry-srv
- docker run
- -v /mnt/registry:/var/lib/registry \
- -v `pwd`/config-srv.yml:/etc/docker/registry/config.yml \
- 测试
- docker tag busybox localhost:5000/busybox
- docker push localhost:5000/busybox
- registry-web
- docker run
- -v $(pwd)/config-web.yml:/conf/config.yml:ro \
- -e REGISTRY_BASIC_AUTH=”`echo adm:123123|base64`” \
- hyper/docker-registry-web
- 参考
- https://hub.docker.com/_/registry/
- https://hub.docker.com/r/hyper/docker-registry-web/
- https://docs.docker.com/registry/configuration/#list-of-configuration-options
- https://blog.csdn.net/mideagroup/article/details/52052618
- https://blog.csdn.net/snipercai/article/details/78589368
- registry portus
- 安装
- git clone https://github.com/SUSE/Portus.git
- sed -i ‘s#https://rubygems.org#http://rubygems.org#’ ./Gemfile
- sed -i ‘s#https://rubygems.org#http://rubygems.org#’ ./Gemfile.lock
- docker清理数据
- docker image prune:删除无用的镜像。
- docker container prune:删除无用的容器。
- docker volume prune:删除无用的卷。
- docker network prune:删除无用的网络。
- docker system prune:删除无用的镜像、容器、卷、网络。
- 压缩镜相工具dive
- docker run –rm -it -v /var/run/docker.sock:/var/run/docker.sock -e DOCKER_API_VERSION=1.39 wagoodman/dive:latest <image name>
- docker搭建基础应用环境
- yum 源
- 示例: openstack.repo:
- name=OpenStack Havana Repository
- createrepo
- createrepo –update /usr/local/apache/htdocs/centos/extra 更新索引
- DNS
- 理论:
- 有如下记录类型:A,AAAA,PTR,SOA,NS,CNAME,MX
- A:Internet Address,作用,FQDN 到 IP
- NS:Name Server,专用于表明当前区域的DNS服务器
- CNAME:Canonical Name,别名记录
- 主从
- 问题:使用docker搭建主从同步,无法同步记录connect refuse
- docker
- docker pull docker.io/jpillora/dnsmasq
- docker run –name dnsmasq -d \
- -p 53:53/udp -p 8080:8080 \
- -v /opt/dnsmasq.conf:/etc/dnsmasq.conf \
- -e “HTTP_USER=admin” -e “HTTP_PASS=admin” \
- –restart always jpillora/dnsmasq
- docker run –name bind -d \
- -e WEBMIN_ENABLED=false \
- -v /opt/bind/entrypoint.sh:/sbin/entrypoint.sh \
- docker-compose
- mkdir /opt/cmp_bind;cd /opt/cmp_bind;
- – /opt/bind/entrypoint.sh:/sbin/entrypoint.sh
- mysql
- 基本命令
- 示例:
- #备份
- mysqldump -uroot -p<pwd> -h172.16.40.7 –all-databases >mysqlbakdate +%Y%m%d-%H%M%S.sql
- mysql -e “show databases;” -uroot -ppassword -h172.16.40.7| grep -Ev “Database|information_schema|mysql|performance_schema|dbtest|sys”| xargs mysqldump -uroot -ppassword -h172.16.40.7 –set-gtid-purged=OFF –no-tablespaces –databases > mysqlbak`date +%Y%m%d-%H%M%S`.sql
- #sql 字符index号,长度:
- select position(‘/’ in @str) as i;
- select substring(@str,position(‘/’ in @str)+1,LENGTH(@str)) join
- select substring(@str,1,position(‘/’ in @str)-1);
- select cast(substring(@str,position(‘/’ in @str)+1,LENGTH(@str)) as decimal);
- $sql=”select `date`,b.hostname,a.ip,cpu,mem,`storage`,net from ($table_name as a inner join hostip as b on trim(a.ip)=trim(b.ip)) order by cast(substring(mem,position(‘/’ in mem)+1,LENGTH(mem)) as decimal)”
- #mysql 加一用户可任意IP登陆
- CREATE USER yanght@’%’ IDENTIFIED BY ‘123456’;
- grant all privileges on *.* to yanght@’%’ identified by ‘123456’;
- #限子网段访问
- grant all on *.* to ‘account’@’192.168.0.%’ identified by ‘acc430’;
- #mysql max_connections
- Edit file /usr/lib/systemd/system/mysqld.service
- $ systemctl daemon-reload
- $ systemctl restart mysqld.service
- #load data:
- LOAD DATA INFILE ‘/home/test/dump/ip_location.csv’
- #create table test.mteveryday select …from…
- #drop table test.mteveryday
- #update join
- UPDATE friends INNER JOIN users ON friends.friendid=users.userid
- SET friends.friendname=users.username
- #insert into
- insert into table1(field1,field2..)
- select col1,col2 from table2
- docker run
- docker run –name yunwei-mariadb \
- -e MYSQL_ROOT_PASSWORD=123321 \
- -v /opt/mysql:/var/lib/mysql \
- docker-compose.yml
- mkdir /opt/cmp_mysql;cd /opt/cmp_mysql;
- – MYSQL_ROOT_PASSWORD=123321
- 双主结构
- 1.优化系统
- cat >>/etc/security/limits.conf<<eof
- cat >>/etc/sysctl.conf<<eof
- 2.配置my.cnf
- #server1——————————
- log_bin = /var/log/mysql/mariadb-bin
- log_bin_index = /var/log/mysql/mariadb-bin.index
- binlog-do-db = tudou1 #需要同步的数据库,这里同步tudou1和tudou2两个数据库
- binlog-ignore-db = mysql #忽略同步的数据库
- log_slave_updates #把从库的写操作记录到binlog中 (缺少之后,双主创建失败)
- expire_logs_days = 365 #日志文件过期天数,默认是 0,表示不过期
- auto_increment_increment= 2 #设定为主服务器的数量,防止auto_increment字段重复
- auto_increment_offset = 1 #自增长字段的初始值,在多台master环境下,不会出现自增长ID重复
- #server2——————————
- log_bin = /var/log/mysql/mariadb-bin
- log_bin_index = /var/log/mysql/mariadb-bin.index
- binlog-do-db = tudou1 #需要同步的数据库,这里同步tudou1和tudou2两个数据库
- binlog-ignore-db = mysql #忽略同步的数据库
- log_slave_updates #把从库的写操作记录到binlog中 (缺少之后,双主创建失败)
- expire_logs_days = 365 #日志文件过期天数,默认是 0,表示不过期
- auto_increment_increment= 2 #设定为主服务器的数量,防止auto_increment字段重复
- auto_increment_offset = 2 #自增长字段的初始值,在多台master环境下,不会出现自增长ID重复
- 3.创建同步账户
- GRANT REPLICATION SLAVE ON *.* TO ‘repuser’@’server-2’ IDENTIFIED BY ‘repuser’;
- GRANT REPLICATION SLAVE ON *.* TO ‘repuser’@’server-1’ IDENTIFIED BY ‘repuser’;
- 可以顺便在另一台服务器测试能不能登录,如果不能,把 bind-address 那行注释掉即可。
- $ mysql -urepuser -prepuser -hserver-1
- 4.查看 master 状态
- MariaDB [mysql]> show master status;
- +——————–+———-+————–+——————+
- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
- +——————–+———-+————–+——————+
- | mariadb-bin.000514 | 639 | xxxxxxxx | mysql |
- +——————–+———-+————–+——————+
- MariaDB [mysql]> show master status;
- +——————–+———-+————–+——————+
- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
- +——————–+———-+————–+——————+
- | mariadb-bin.000006 | 1057 | xxxxxxxx | mysql |
- +——————–+———-+————–+——————+
- 5.设置同步
- MariaDB [mysql]> CHANGE MASTER TO MASTER_HOST=’server-1′,MASTER_PORT=3306,MASTER_USER=’repuser’,MASTER_PASSWORD=’repuser’,MASTER_LOG_FILE=’mariadb-bin.000514′,MASTER_LOG_POS=639;
- MariaDB [mysql]> START SLAVE;
- MariaDB [mysql]> CHANGE MASTER TO MASTER_HOST=’server-2′,MASTER_PORT=3306,MASTER_USER=’repuser’,MASTER_PASSWORD=’repuser’,MASTER_LOG_FILE=’mariadb-bin.000006′,MASTER_LOG_POS=1057;
- MariaDB [mysql]> START SLAVE;
- 6.测试:
- MariaDB [mysql]> SHOW SLAVE STATUS\G
- 在服务器 1 数据库中创建一个表,看看服务器 2 会不会出现,按照上面教程,如果没问题的话,就是可以同步的。
- mariadb-server-galeara 多主结构
- nfs
- docker
- -v /some/where/fileshare:/nfsshare \
- -e SHARED_DIRECTORY=/nfsshare \
- itsthenetwork/nfs-server-alpine:latest
- docker-compose
- mkdir /opt/cmp1_nfs;cd /opt/cmp_nfs;
- image: itsthenetwork/nfs-server-alpine
- # Required to load kernel NFS module
- – SHARED_DIRECTORY=/nfsshare
- exportfs
- /nfsshare *(rw,fsid=0,async,no_subtree_check,no_auth_nlm,insecure,no_root_squash)
- #注意:将原root_squash改为no_root_squash,否则root将不能写挂载的NFS卷
- #client:
- mount -t nfs4 <host>:/ /opt
- NGINX
- docker run
- docker run –name mynginx \
- -v /opt/nginx:/etc/nginx \
- -v /opt/nginxlog:/var/log/nginx \
- -v /opt/nginx/hosts:/etc/hosts \
- docker-compose.yml
- mkdir /opt/cmp_nginx;cd /opt/cmp_nginx;
- – /opt/nginxlog:/var/log/nginx
- – /opt/nginx/hosts:/etc/hosts
- http 下载
- #more download.yunwei.edu.conf
- server_name download.yunwei.edu;
- access_log /var/log/nginx/download.access_log access;
- error_log /var/log/nginx/download.error_log info;
- autoindex_exact_size off;
- #关闭详细文件大小统计,让文件大小显示MB,GB单位,默认为b;
- if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|tgz
- add_header Content-Disposition: ‘attachment;’;
- 参考:
- http://blog.csdn.net/hzsunshine/article/details/63687054
- http://blog.csdn.net/zzq900503/article/details/70049348
- https://www.cnblogs.com/zhouxinfei/p/7862285.html
- openvpn
- docker-compose.yml
- mkdir cmp_ovpn;cd cmp_ovpn
- – ./ovpn_data:/etc/openvpn
- 配置:
- server: openvpn.conf
- ================================================
- server 192.168.255.0 255.255.255.0
- key /etc/openvpn/pki/private/192.168.31.140.key
- ca /etc/openvpn/pki/ca.crt
- cert /etc/openvpn/pki/issued/192.168.31.140.crt
- dh /etc/openvpn/pki/dh.pem
- tls-auth /etc/openvpn/pki/ta.key
- # Rely on Docker to do port mapping, internally always 1194
- status /tmp/openvpn-status.log
- client-config-dir /etc/openvpn/ccd
- ### Route Configurations Below
- route 192.168.254.0 255.255.255.0
- ### Push Configurations Below
- push “dhcp-option DNS 114.114.114.114”
- push “dhcp-option DNS 223.5.5.5”
- server: ccd
- ====================================================
- root@docker116:50:12/opt/ovpn_data#more ccd/client*
- ifconfig-push 192.168.255.10 192.168.255.9
- ifconfig-push 192.168.255.14 192.168.255.13
- ifconfig-push 192.168.255.18 192.168.255.17
- 生成证书与client配置
- docker pull kylemanna/openvpn
- #OVPN_DATA=”/root/ovpn-data”
- OVPN_DATA=”/opt/cmp_ovpn/ovpn_data”
- docker run -v ${OVPN_DATA}:/etc/openvpn –rm kylemanna/openvpn ovpn_genconfig -u tcp://${IP}
- docker run -v ${OVPN_DATA}:/etc/openvpn –rm -it kylemanna/openvpn ovpn_initpki
- Enter PEM pass phrase: 输入123456(你是看不见的)
- Verifying – Enter PEM pass phrase: 输入123456(你是看不见的)
- Common Name (eg: your user, host, or server name) [Easy-RSA CA]:回车一下
- Enter pass phrase for /etc/openvpn/pki/private/ca.key:输入123456
- #docker run -v ${OVPN_DATA}:/etc/openvpn –rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass
- docker run -v ${OVPN_DATA}:/etc/openvpn –rm -it kylemanna/openvpn easyrsa build-client-full client1 nopass
- Enter pass phrase for /etc/openvpn/pki/private/ca.key:输入123321
- #docker run -v ${OVPN_DATA}:/etc/openvpn –rm kylemanna/openvpn ovpn_getclient CLIENTNAME > ${OVPN_DATA}/CLIENTNAME.ovpn
- docker run -v ${OVPN_DATA}:/etc/openvpn –rm kylemanna/openvpn ovpn_getclient client1 > ${OVPN_DATA}/client1.ovpn
- docker run –name openvpn -v ${OVPN_DATA}:/etc/openvpn -d -p 1194:1194 –privileged kylemanna/openvpn
- 增加client
- OVPN_DATA=”/opt/cmp_ovpn/ovpn_data”
- docker run -v ${OVPN_DATA}:/etc/openvpn –rm -it kylemanna/openvpn easyrsa build-client-full $NAME nopass
- docker run -v ${OVPN_DATA}:/etc/openvpn –rm kylemanna/openvpn ovpn_getclient $NAME > ${OVPN_DATA}/$NAME.ovpn
- sed -i ‘s/192.168.31.140/139.198.16.150/’ ${OVPN_DATA}/$NAME.ovpn
- 路由与NAT
- iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
- vsFTP
- docker-compose.yml
- mkdir /opt/cmp_vsftpd;cd /opt/cmp_vsftpd;
- – “21100-21110:21100-21110”
- – ./vsftpd.conf:/etc/vsftpd/vsftpd.conf
- – ./run-vsftpd.sh:/usr/sbin/run-vsftpd.sh
- # – PASV_ADDRESS=192.168.100.222
- docker run
- -v /my/data/directory:/home/vsftpd \
- -p 21100-21110:21100-21110 \
- -e FTP_USER=myuser -e FTP_PASS=mypass \
- -e PASV_ADDRESS=127.0.0.1 \
- vsftpd.conf
- # Run in the foreground to keep the container running:
- # Allow anonymous FTP? (Beware – allowed by default if you comment this out).
- anon_world_readable_only=yes
- anon_other_write_enable=YES
- anon_mkdir_write_enable=yes
- anon_root=/home/vsftpd/anonymous
- # Uncomment this to allow local users to log in.
- ## Virtual users will use the same permissions as anonymous
- virtual_use_local_privs=YES
- # Uncomment this to enable any form of FTP write command.
- pam_service_name=vsftpd_virtual
- ## Home Directory for virtual users
- # You may specify an explicit list of local users to chroot() to their home
- # directory. If chroot_local_user is YES, then this list becomes a list of
- # Workaround chroot check.
- # See https://www.benscobie.com/fixing-500-oops-vsftpd-refusing-to-run-with-writable-root-inside-chroot/
- # and http://serverfault.com/questions/362619/why-is-the-chroot-local-user-of-vsftpd-insecure
- allow_writeable_chroot=YES
- ## Set passive port address
- xferlog_file=/var/log/vsftpd/vsftpd.log
- ## Disable seccomp filter sanboxing
- pasv_address=192.168.31.141
- run-vsftpd.sh
- # If no env var for FTP_USER has been specified, use ‘admin’:
- if [ “$FTP_USER” = “**String**” ]; then
- # If no env var has been specified, generate a random password for FTP_USER:
- if [ “$FTP_PASS” = “**Random**” ]; then
- export FTP_PASS=`cat /dev/urandom | tr -dc A-Z-a-z-0-9 | head -c${1:-16}`
- # Do not log to STDOUT by default:
- if [ “$LOG_STDOUT” = “**Boolean**” ]; then
- # Create home dir and update vsftpd user db:
- mkdir -p “/home/vsftpd/${FTP_USER}”
- chown -R ftp:ftp /home/vsftpd/
- echo -e “${FTP_USER}\n${FTP_PASS}” > /etc/vsftpd/virtual_users.txt
- /usr/bin/db_load -T -t hash -f /etc/vsftpd/virtual_users.txt /etc/vsftpd/virtual_users.db
- # Set passive mode parameters:
- if [ “$PASV_ADDRESS” = “**IPv4**” ]; then
- export PASV_ADDRESS=$(/sbin/ip route|awk ‘/default/ { print $3 }’)
- ###echo “pasv_address=${PASV_ADDRESS}” >> /etc/vsftpd/vsftpd.conf
- ###echo “pasv_max_port=${PASV_MAX_PORT}” >> /etc/vsftpd/vsftpd.conf
- ###echo “pasv_min_port=${PASV_MIN_PORT}” >> /etc/vsftpd/vsftpd.conf
- export LOG_FILE=`grep xferlog_file /etc/vsftpd/vsftpd.conf|cut -d= -f2`
- if [ ! $LOG_STDOUT ]; then
- *************************************************
- * Docker image: fauria/vsftd *
- * https://github.com/fauria/docker-vsftpd *
- *************************************************
- · FTP Password: $FTP_PASS
- · Redirect vsftpd log to STDOUT: No.
- /usr/bin/ln -sf /dev/stdout $LOG_FILE
- &>/dev/null /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
- sendmail
- dockerfile
- mkdir /opt/cmp_sendmail; cd /opt/cmp_sendmail
- MAINTAINER yht yanght “me@yunwei.edu”
- RUN set -e && apt-get update && apt-get install -y sendmail
- #COPY sendmail.mc /etc/mail/sendmail.mc
- RUN m4 sendmail.mc > sendmail.cf && \
- echo “Connect:172 RELAY” >> access && \
- echo “Connect:10 RELAY” >> access && \
- echo “Connect:192 RELAY” >> access && \
- echo “Connect:yunwei.edu RELAY” >> access && \
- CMD /usr/lib/sendmail -bD -X /proc/self/fd/1
- docker run配置
- docker build -t ubuntu.sendmail ./
- docker run –name sendmail -p 25:25 -d ubuntu.sendmail
- docker cp sendmail:/etc/mail/sendmail.mc .
- sed ‘s/127.0.0.1/0.0.0.0/g’ sendmail.mc
- docker cp ./sendmail.mc sendmail:/etc/mail/sendmail.mc
- docker exec -it sendmail bash
- m4 sendmail.mc >sendmail.cf
- docker-compose
- – ./sendmail.cf:/etc/mail/sendmail.cf
- – ./access.db:/etc/mail/access.db
- DHCP
- 固定IP分配
- host Client_C { #有一个主机,叫Client_C
- hardware ethernet 08:00:27:5e:04:27; #MAC地址是08:…:27的网卡
- fixed-address 192.168.233.123;#分配给它192.168.233.123的IP
- kubernetes
- 概念
- svc pod node ep container
- clusterip ep nodeip containerip
- Kubernetes是:
- Kubernetes是Google开源的容器集群管理系统,是Docker容器的主要集群管理系统之一。
- 主要功能如下:
- 1)将多台Docker主机抽象为一个资源,以集群方式管理容器,包括任务调度、资源管理、弹性伸缩、滚动升级等功能。
- 2)使用编排系统(YAML File)快速构建容器集群,提供负载均衡,解决容器直接关联及通信问题
- 3)自动管理和修复容器,简单说,比如创建一个集群,里面有十个容器,如果某个容器异常关闭,那么,会尝试重启或重新分配容器,始终保证会有十个容器在运行,反而杀死多余的。
- Kubernetes中的PodIP、ClusterIP和外部IP
- Kubernetes中管理主要有三种类型的IP:Pod IP 、Cluster IP 和 外部IP。
- Pod IP
- Kubernetes的最小部署单元是Pod。利用Flannel作为不同HOST之间容器互通技术时,由Flannel和etcd维护了一张节点间的路由表。Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。
- 每个Pod启动时,会自动创建一个镜像为gcr.io/google_containers/pause:0.8.0的容器,容器内部与外部的通信经由此容器代理,该容器的IP也可以称为Pod IP。
- Cluster IP
- Pod IP 地址是实际存在于某个网卡(可以是虚拟设备)上的,但Service Cluster IP就不一样了,没有网络设备为这个地址负责。它是由kube-proxy使用Iptables规则重新定向到其本地端口,再均衡到后端Pod的。
- 就拿上面我们提到的图像处理程序为例。当我们的Service被创建时,Kubernetes给它分配一个地址10.0.0.1。这个地址从我们启动API的service-cluster-ip-range参数(旧版本为portal_net参数)指定的地址池中分配,比如–service-cluster-ip-range=10.0.0.0/16。假设这个Service的端口是1234。集群内的所有kube-proxy都会注意到这个Service。当proxy发现一个新的service后,它会在本地节点打开一个任意端口,建相应的iptables规则,重定向服务的IP和port到这个新建的端口,开始接受到达这个服务的连接。
- 当一个客户端访问这个service时,这些iptable规则就开始起作用,客户端的流量被重定向到kube-proxy为这个service打开的端口上,kube-proxy随机选择一个后端pod来服务客户。这个流程如下图所示:
- 根据Kubernetes的网络模型,使用Service Cluster IP和Port访问Service的客户端可以坐落在任意代理节点上。外部要访问Service,我们就需要给Service外部访问IP。
- 外部IP
- Service对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个Service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。
- 外部访问者是访问集群代理节点的访问者。为这些访问者提供服务,我们可以在定义Service时指定其spec.publicIPs,一般情况下publicIP 是代理节点的物理IP地址。和先前的Cluster IP range上分配到的虚拟的IP一样,kube-proxy同样会为这些publicIP提供Iptables 重定向规则,把流量转发到后端的Pod上。有了publicIP,我们就可以使用load balancer等常用的互联网技术来组织外部对服务的访问了。
- spec.publicIPs在新的版本中标记为过时了,代替它的是spec.type=NodePort,这个类型的service,系统会给它在集群的各个代理节点上分配一个节点级别的端口,能访问到代理节点的客户端都能访问这个端口,从而访问到服务。
- kubernetes角色组成:
- 1)Pod
- Pod是kubernetes的最小操作单元,一个Pod可以由一个或多个容器组成;同一个Pod只能运行在同一个主机上,共享相同的volumes、network、namespace;
- 2)ReplicationController(RC)
- RC用来管理Pod,一个RC可以由一个或多个Pod组成,在RC被创建后,系统会根据定义好的副本数来创建Pod数量。在运行过程中,如果Pod数量小于定义的,就会重启停止的或重新分配Pod,反之则杀死多余的。当然,也可以动态伸缩运行的Pods规模。
- RC通过label关联对应的Pods,在滚动升级中,RC采用一个一个替换要更新的整个Pods中的Pod。
- Replication Controller是Kubernetes系统中最有用的功能,实现复制多个Pod副本,往往一个应用需要多个Pod来支撑,并且可以保证其复制的副本数,即使副本所调度分配的主宿机出现异常,通过Replication Controller可以保证在其它主宿机启用同等数量的Pod。Replication Controller可以通过repcon模板来创建多个Pod副本,同样也可以直接复制已存在Pod,需要通过Label selector来关联。
- 3)Service
- Service定义了一个Pod逻辑集合的抽象资源,Pod集合中的容器提供相同的功能。集合根据定义的Label和selector完成,当创建一个Service后,会分配一个Cluster IP,这个IP与定义的端口提供这个集合一个统一的访问接口,并且实现负载均衡。
- Services是Kubernetes最外围的单元,通过虚拟一个访问IP及服务端口,可以访问我们定义好的Pod资源,目前的版本是通过iptables的nat转发来实现,转发的目标端口为Kube_proxy生成的随机端口
- 4)Label
- Label是用于区分Pod、Service、RC的key/value键值对;
- Pod、Service、RC可以有多个label,但是每个label的key只能对应一个;
- 主要是将Service的请求通过lable转发给后端提供服务的Pod集合;
- Labels是用于区分Pod、Service、Replication Controller的key/value键值对,仅使用在Pod、Service、 Replication Controller之间的关系识别,但对这些单元本身进行操作时得使用name标签。
- 5) Proxy
- Proxy不但解决了同一主宿机相同服务端口冲突的问题,还提供了Service转发服务端口对外提供服务的能力,Proxy后端使用了随机、轮循负载均衡算法。
- kubernetes组件组成:
- 1)kubectl
- 客户端命令行工具,将接受的命令格式化后发送给kube-apiserver,作为整个系统的操作入口。
- 2)kube-apiserver
- 作为整个系统的控制入口,以REST API服务提供接口。
- 3)kube-controller-manager
- 用来执行整个系统中的后台任务,包括节点状态状况、Pod个数、Pods和Service的关联等。
- 4)kube-scheduler
- 负责节点资源管理,接受来自kube-apiserver创建Pods任务,并分配到某个节点。
- 6)kube-proxy
- 运行在每个计算节点上,负责Pod网络代理。定时从etcd获取到service信息来做相应的策略。
- 7)kubelet
- 运行在每个计算节点上,作为agent,接受分配该节点的Pods任务及管理容器,周期性获取容器状态,反馈给kube-apiserver。
- 8)DNS
- 一个可选的DNS服务,用于为每个Service对象创建DNS记录,这样所有的Pod就可以通过DNS访问服务了。
- Kubernetes 暴露服务的有三种方式
- 我们知道,到目前为止 Kubernetes 暴露服务的有三种方式,分别为 LoadBlancer Service、NodePort Service、Ingress。
- 官网对 Ingress 的定义为管理对外服务到集群内服务之间规则的集合,通俗点讲就是它定义规则来允许进入集群的请求被转发到集群中对应服务上,从来实现服务暴漏。 Ingress 能把集群内 Service 配置成外网能够访问的 URL,流量负载均衡,终止SSL,提供基于域名访问的虚拟主机等等。
- LoadBlancer Service
- LoadBlancer Service 是 Kubernetes 结合云平台的组件,如国外 GCE、AWS、国内阿里云等等,使用它向使用的底层云平台申请创建负载均衡器来实现,有局限性,对于使用云平台的集群比较方便。
- NodePort Service
- NodePort Service 是通过在节点上暴漏端口,然后通过将端口映射到具体某个服务上来实现服务暴漏,比较直观方便,但是对于集群来说,随着 Service 的不断增加,需要的端口越来越多,很容易出现端口冲突,而且不容易管理。当然对于小规模的集群服务,还是比较不错的。
- Ingress
- Ingress 使用开源的反向代理负载均衡器来实现对外暴漏服务,比如 Nginx、Apache、Haproxy等。Nginx Ingress 一般有三个组件组成:
- Ingress Controller
- Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端 Service、Pod 等的变化,比如新增、删除等,然后结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
- Ingress
- Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。