微信号:david-share

介绍:乐于分享,才有进步.

Openshift高阶探索实验

2018-02-24 19:28 魏新宇


前言

本文包含如下内容:HA方式部署Openshift、Openshift SDN探究、Openshift SDN的网络策略实验、Openshift的资源管理管理。


本文仅为笔者的读书笔记,仅作为技术探讨和参考,不能作为Openshift生产部署的标准。本文仅代表笔者的个人观点。



一、HA方式部署Openshift


一个典型的OCP高可用架构是:master至少应为三个,且为奇数个(上面有etcd);


基础架构节点不少于两个,上面运行日志、监控、router、INTEGRATED REGISTRY。

Openshift的计算节点不少于2个,以保证当一个节点出现故障的时候,不影响应用。


Openshift中,两个重要的流量入口组件是Master和Router。

在生产环境中,为了保证高可用,Master和Router都会配置多个。这就引入了一个问题:多个Master和Router对外如何提供统一的域名。


这时候,需要使用客户数据中心/公有云的负载均衡。当然,在数据中心内,我们也可以通过Haproxy搭建软负载,这和使用F5的设备无本质区别。

在考虑流量入口的负载均衡的同时,我们还需要考虑DNS的问题。当然,商业的F5通常有DNS的功能。


针对Master,多个Master会有一个VIP/域名。VIP和多个Master都需要被DNS解析。在负载均衡器上,将Master VIP的域名(如master.ocp.example.com)和多个Master的域名对应起来,同时设置负载均衡策略,如roundrobin等。


针对Router, DNS需要将应用对外的域名,解析成router所在的openshift节点的域名。如果有多个router,就需要个多个router配置VIP和它的域名。VIP被解析成多个router所在的Openshift节点的域名(同时配置负载均衡策略)。而DNS上进行配置,对应用对泛域名解析,将其解析成router的VIP。



在Openshift中,etcd做服务发现,其K-V数据库存放Openshift的信息。


为了保证etcd的高可用,在生产环境中,etcd应配置成奇数个(2n+1),并且每个etcd成员之间的网络延迟小于5ms。


在Openshift中,建议将etcd与Master节点部署到一起。也就是三个master上,每个master上一个etcd。



目前Openshift的日志使用EFK,具体概念不展开讲,请参照其他文档。


在EFK中,Elasticsearch需要高可用,和etcd一样,需要2n+1个节点,以保证高可用并规避脑裂。



在Openshift的监控数据中,Cassandra分布式数据库存放监控信息,因此需要做高可用。在多个Cassandra之间,做存储的复制。



在Openshift中,集成镜像仓库通常用于存放dev成功后的镜像,以完成整个CI/CD过程。他与数据中心外部镜像仓库是分开的,作用也不一样。


在生产环境中,INTEGRATED REGISTRY通常会被配置成多个。


同样,需要给多个REGISTRY配置VIP和域名。多个REGISTRY的VIP通过负载均衡器的roundrbin指向多个registery。



在本实验中,Openshift的架构如下:


首先登录到管理节点,编辑/etc/ansible/hosts,内容如下(需要注意的是:下面内容用于ansible安装整套环境,使用的是节点的内部名称,而非上面列出的public FQDN):


安装的时候,网络模式选择openshift-ovs-multitenant。

cat  /etc/ansible/hosts


[OSEv3:vars]


###########################################################################

### Ansible Vars

###########################################################################

timeout=60

ansible_become=yes

ansible_ssh_user=ec2-user


###########################################################################

### OpenShift Basic Vars

###########################################################################

deployment_type=openshift-enterprise

containerized=false

openshift_disable_check="disk_availability,memory_availability"


# default project node selector

osm_default_node_selector='env=app'


# Configure node kubelet arguments. pods-per-core is valid in OpenShift Origin 1.3 or OpenShift Container Platform 3.3 and later.

openshift_node_kubelet_args={'pods-per-core': ['10'], 'max-pods': ['250'], 'image-gc-high-threshold': ['85'], 'image-gc-low-threshold': ['75']}


# Configure logrotate scripts

# See: https://github.com/nickhammond/ansible-logrotate

logrotate_scripts=[{"name": "syslog", "path": "/var/log/cron\n/var/log/maillog\n/var/log/messages\n/var/log/secure\n/var/log/spooler\n", "options": ["daily", "rotate 7","size 500M", "compress", "sharedscripts", "missingok"], "scripts": {"postrotate": "/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true"}}]

###########################################################################

### OpenShift Optional Vars

###########################################################################


# Enable cockpit

osm_use_cockpit=true

osm_cockpit_plugins=['cockpit-kubernetes']


###########################################################################

### OpenShift Master Vars

###########################################################################


openshift_master_api_port=443

openshift_master_console_port=443


openshift_master_cluster_method=native

openshift_master_cluster_hostname=loadbalancer.db84.example.opentlc.com

openshift_master_cluster_public_hostname=loadbalancer.db84.example.opentlc.com

openshift_master_default_subdomain=apps.db84.example.opentlc.com


openshift_master_overwrite_named_certificates=True

openshift_master_ca_certificate={'certfile': '/root/intermediate_ca.crt', 'keyfile': '/root/intermediate_ca.key'}


openshift_set_hostname=True


###########################################################################

### OpenShift Network Vars

###########################################################################


osm_cluster_network_cidr=10.1.0.0/16

openshift_portal_net=172.30.0.0/16


os_sdn_network_plugin_name='redhat/openshift-ovs-multitenant'

#os_sdn_network_plugin_name='redhat/openshift-ovs-subnet'


# This should be turned on once all dependent scripts use firewalld rather than iptables

# os_firewall_use_firewalld=True


###########################################################################

### OpenShift Authentication Vars

###########################################################################

# htpasswd auth

openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}]

# Defining htpasswd users

#openshift_master_htpasswd_users={'user1': '<pre-hashed password>', 'user2': '<pre-hashed password>'}

# or

openshift_master_htpasswd_file=/root/htpasswd.openshift

###########################################################################

### OpenShift Metrics and Logging Vars

###########################################################################


# Enable cluster metrics


openshift_metrics_install_metrics=True


openshift_metrics_storage_kind=nfs

openshift_metrics_storage_access_modes=['ReadWriteOnce']

openshift_metrics_storage_nfs_directory=/srv/nfs

openshift_metrics_storage_nfs_options='*(rw,root_squash)'

openshift_metrics_storage_volume_name=metrics

openshift_metrics_storage_volume_size=10Gi

openshift_metrics_storage_labels={'storage': 'metrics'}


#openshift_master_metrics_public_url=https://hawkular-metrics.apps.db84.example.opentlc.com/hawkular/metrics


## Add Prometheus Metrics:

openshift_hosted_prometheus_deploy=true

openshift_prometheus_node_selector={"env":"infra"}

openshift_prometheus_namespace=openshift-metrics


# Prometheus

openshift_prometheus_storage_kind=nfs

openshift_prometheus_storage_access_modes=['ReadWriteOnce']

openshift_prometheus_storage_nfs_directory=/srv/nfs

openshift_prometheus_storage_nfs_options='*(rw,root_squash)'

openshift_prometheus_storage_volume_name=prometheus

openshift_prometheus_storage_volume_size=10Gi

openshift_prometheus_storage_labels={'storage': 'prometheus'}

openshift_prometheus_storage_type='pvc'

# For prometheus-alertmanager

openshift_prometheus_alertmanager_storage_kind=nfs

openshift_prometheus_alertmanager_storage_access_modes=['ReadWriteOnce']

openshift_prometheus_alertmanager_storage_nfs_directory=/srv/nfs

openshift_prometheus_alertmanager_storage_nfs_options='*(rw,root_squash)'

openshift_prometheus_alertmanager_storage_volume_name=prometheus-alertmanager

openshift_prometheus_alertmanager_storage_volume_size=10Gi

openshift_prometheus_alertmanager_storage_labels={'storage': 'prometheus-alertmanager'}

openshift_prometheus_alertmanager_storage_type='pvc'

# For prometheus-alertbuffer

openshift_prometheus_alertbuffer_storage_kind=nfs

openshift_prometheus_alertbuffer_storage_access_modes=['ReadWriteOnce']

openshift_prometheus_alertbuffer_storage_nfs_directory=/srv/nfs

openshift_prometheus_alertbuffer_storage_nfs_options='*(rw,root_squash)'

openshift_prometheus_alertbuffer_storage_volume_name=prometheus-alertbuffer

openshift_prometheus_alertbuffer_storage_volume_size=10Gi

openshift_prometheus_alertbuffer_storage_labels={'storage': 'prometheus-alertbuffer'}

openshift_prometheus_alertbuffer_storage_type='pvc'


openshift_metrics_cassandra_nodeselector={"env":"infra"}

openshift_metrics_hawkular_nodeselector={"env":"infra"}

openshift_metrics_heapster_nodeselector={"env":"infra"}


# Enable cluster logging


openshift_logging_install_logging=True


openshift_logging_storage_kind=nfs

openshift_logging_storage_access_modes=['ReadWriteOnce']

openshift_logging_storage_nfs_directory=/srv/nfs

openshift_logging_storage_nfs_options='*(rw,root_squash)'

openshift_logging_storage_volume_name=logging

openshift_logging_storage_volume_size=10Gi

openshift_logging_storage_labels={'storage': 'logging'}


# openshift_logging_kibana_hostname=kibana.apps.db84.example.opentlc.com

openshift_logging_es_cluster_size=1



openshift_logging_es_nodeselector={"env":"infra"}

openshift_logging_kibana_nodeselector={"env":"infra"}

openshift_logging_curator_nodeselector={"env":"infra"}


###########################################################################

### OpenShift Project Management Vars

###########################################################################


# Configure additional projects

openshift_additional_projects={'my-infra-project-test': {'default_node_selector': 'env=infra'}}


###########################################################################

### OpenShift Router and Registry Vars

###########################################################################


openshift_hosted_router_selector='env=infra'

openshift_hosted_router_replicas=2

#openshift_hosted_router_certificate={"certfile": "/path/to/router.crt", "keyfile": "/path/to/router.key", "cafile": "/path/to/router-ca.crt"}


openshift_hosted_registry_selector='env=infra'

openshift_hosted_registry_replicas=1


openshift_hosted_registry_storage_kind=nfs

openshift_hosted_registry_storage_access_modes=['ReadWriteMany']

openshift_hosted_registry_storage_nfs_directory=/srv/nfs

openshift_hosted_registry_storage_nfs_options='*(rw,root_squash)'

openshift_hosted_registry_storage_volume_name=registry

openshift_hosted_registry_storage_volume_size=20Gi

openshift_hosted_registry_pullthrough=true

openshift_hosted_registry_acceptschema2=true

openshift_hosted_registry_enforcequota=true



###########################################################################

### OpenShift Service Catalog Vars

###########################################################################


openshift_enable_service_catalog=true

template_service_broker_install=true

openshift_template_service_broker_namespaces=['openshift']


openshift_hosted_etcd_storage_kind=nfs

openshift_hosted_etcd_storage_nfs_options="*(rw,root_squash,sync,no_wdelay)"

openshift_hosted_etcd_storage_nfs_directory=/srv/nfs

openshift_hosted_etcd_storage_volume_name=etcd-vol2

openshift_hosted_etcd_storage_access_modes=["ReadWriteOnce"]

openshift_hosted_etcd_storage_volume_size=5G

openshift_hosted_etcd_storage_labels={'storage': 'etcd'}


###########################################################################

### OpenShift Hosts

###########################################################################

[OSEv3:children]

lb

masters

etcd

nodes

nfs


[lb]

loadbalancer1.db84.internal host_zone=eu-central-1b


[masters]

master3.db84.internal host_zone=eu-central-1b

master1.db84.internal host_zone=eu-central-1b

master2.db84.internal host_zone=eu-central-1b


[etcd]

master3.db84.internal host_zone=eu-central-1b

master1.db84.internal host_zone=eu-central-1b

master2.db84.internal host_zone=eu-central-1b



[nodes]

## These are the masters

master3.db84.internal openshift_hostname=master3.db84.internal openshift_node_labels="{'logging':'true','openshift_schedulable':'False','cluster': 'db84', 'zone': 'eu-central-1b'}"

master1.db84.internal openshift_hostname=master1.db84.internal openshift_node_labels="{'logging':'true','openshift_schedulable':'False','cluster': 'db84', 'zone': 'eu-central-1b'}"

master2.db84.internal openshift_hostname=master2.db84.internal openshift_node_labels="{'logging':'true','openshift_schedulable':'False','cluster': 'db84', 'zone': 'eu-central-1b'}"


## These are infranodes

infranode1.db84.internal openshift_hostname=infranode1.db84.internal  openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'infra', 'zone': 'eu-central-1b'}"

infranode2.db84.internal openshift_hostname=infranode2.db84.internal  openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'infra', 'zone': 'eu-central-1b'}"


## These are regular nodes

node2.db84.internal openshift_hostname=node2.db84.internal  openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'app', 'zone': 'eu-central-1b'}"

node1.db84.internal openshift_hostname=node1.db84.internal  openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'app', 'zone': 'eu-central-1b'}"



[nfs]

support1.db84.internal openshift_hostname=support1.db84.internal


接下来,确认所有节点都可以访问:

#sudo ansible all -m ping



确认OCP集群中的节点Docker都已经安装并启动。

ansible all -m shell -a"systemctl status docker"

确认NFS server配置正确:


查看repo:


通过ansible的方式,在管理节点上部署OCP.

首先下载证书:

wget http://ipa.shared.example.opentlc.com/ipa/config/ca.crt -O /root/ipa-ca.crt

这个证书会与实验环境中的IDM进行认证。


获取用于签署OpenShift系统中所有密钥的“中介CA”密钥和证书。


# wget http://admin.na.shared.opentlc.com/certificates/intermediate.cert.pem -O /root/intermediate_ca.crt

# wget http://admin.na.shared.opentlc.com/certificates/intermediate.key.pem -O /root/intermediate_ca.key


接下来,执行ansible-playbook安装OCP:

#ansible-playbook -f 20 /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml


查看节点,都安装成功:

检查证书是否已经部署到master上:

已经部署成功。


查看master节点上的证书:

ansible masters -m shell -a 'for x in $(ls /etc/origin/master/*.crt); do \echo $x; openssl x509 -subject -issuer -in ${x} -noout; echo; done' | less

查看node上的证书:

ansible nodes -m shell -a 'for x in $(ls /etc/origin/node/*.crt); do \

echo $x; openssl x509 -subject -issuer -in ${x} -noout; echo;done' | less


OCP安装成功以后,访问master是通过访问loadbalance实现的:



接下来,在NFS server上创建目录,这将作为后续PV使用:

mkdir -p /srv/nfs/user-vols/pv{1..200}


for pvnum in {1..50} ; do

echo /srv/nfs/user-vols/pv${pvnum} *(rw,root_squash) >> /etc/exports.d/openshift-uservols.exports

chown -R nfsnobody.nfsnobody  /srv/nfs

chmod -R 777 /srv/nfs

done


systemctl restart nfs-server


在master1上创建25个每个5G大小PV的配置文件:

export GUID=`hostname|awk -F. '{print $2}'`

echo $GUID


export volsize="5Gi"

mkdir /root/pvs

for volume in pv{1..25} ; do

cat << EOF > /root/pvs/${volume}

{

  "apiVersion": "v1",

  "kind": "PersistentVolume",

  "metadata": {

    "name": "${volume}"

  },

  "spec": {

    "capacity": {

        "storage": "${volsize}"

    },

    "accessModes": [ "ReadWriteOnce" ],

    "nfs": {

        "path": "/srv/nfs/user-vols/${volume}",

        "server": "support1.${GUID}.internal"

    },

    "persistentVolumeReclaimPolicy": "Recycle"

  }

}

EOF

echo "Created def file for ${volume}";

done;


在master1上创建25个每个10G大小PV的配置文件:

export volsize="10Gi"

for volume in pv{26..50} ; do

cat << EOF > /root/pvs/${volume}

{

  "apiVersion": "v1",

  "kind": "PersistentVolume",

  "metadata": {

    "name": "${volume}"

  },

  "spec": {

    "capacity": {

        "storage": "${volsize}"

    },

    "accessModes": [ "ReadWriteMany" ],

    "nfs": {

        "path": "/srv/nfs/user-vols/${volume}",

        "server": "support1.${GUID}.internal"

    },

    "persistentVolumeReclaimPolicy": "Retain"

  }

}

EOF

echo "Created def file for ${volume}";

done;



最后,创建pv:

cat pvs/* | oc create -f -



二、Openshift SDN多租户模式探究


OCP的安装使用的是多租户的模式。

我们查看project,可以看到NetID:


接下来,创建两个项目并在项目中部署应用:

oc new-project pizzaparty-dev

oc new-project fancypants-dev


oc new-app openshift/hello-openshift:v1.1.1.1 -n pizzaparty-dev

oc new-app openshift/hello-openshift:v1.1.1.1 -n fancypants-dev


查看pod:

在两个项目中各创建一个起bash的pod:

查看项目的netid:

接下来,我们看一下新创建的两个项目之间是否是相互隔离的。


先找出两个项目中的两个pod的IP:

我们登录第一个项目的shelly pod:

先访问非本项目的pod,失败:

访问本项目的pod:


这说明ovs的多租户模式,使项目之间的网络隔离。


接下来,我们对两个项目做join操作:

oadm pod-network join-projects --to=fancypants-dev pizzaparty-dev

然后再进行测试,不同项目之间的网络已经打通:



三、Openshift SDN Service Layer探究

创建一个新的项目,并部署一个应用:

#oc new-project servicelayer

# oc new-app openshift/hello-openshift

将pod副本扩展为4:

oc scale dc/hello-openshift --replicas=4

查看刚创建应用的service layer:

oc describe service hello-openshift

可以看到service ip是172.30.198.53。


查看iptabls上80端口对于本应用的规则:

iptables-save | grep servicelayer/hello-openshift | grep 8080 |grep -i 172.30.198.53


-A KUBE-SERVICES -d 172.30.198.53/32 -p tcp -m comment --comment "servicelayer/hello-openshift:8080-tcp cluster IP" -m tcp --dport 8080 -j KUBE-SVC-BXIL3WE3EN2EVZ7N


这条规则关联到新的规则链:KUBE-SVC-BXIL3WE3EN2EVZ7N


我们查看BXIL3WE3EN2EVZ7N下一跳:

iptables-save | grep servicelayer/hello-openshift | grep -i KUBE-SVC-BXIL3WE3EN2EVZ7N

再查看其下一跳,可以看到是pod的IP:

也就是说,iptables的规则中:对server ip的访问,在经过两跳以后,转到了pod的IP上。


接下来,我们检测 Session Affinity:

oc edit service hello-openshift,将 Session Affinity:从None修改为ClientIP:

我们再次查看iptables的规则:

iptables-save | grep servicelayer/hello-openshift | grep 8080| grep -i 172.30.152.146

-A KUBE-SERVICES -d 172.30.198.53/32 -p tcp -m comment --comment "servicelayer/hello-openshift:8080-tcp cluster IP" -m tcp --dport 8080 -j KUBE-SVC-BXIL3WE3EN2EVZ7N


查看KUBE-SVC-BXIL3WE3EN2EVZ7N的下一跳:

iptables-save | grep servicelayer/hello-openshift | grep -i  KUBE-SVC-BXIL3WE3EN2EVZ7N

看到修改与Session Affinity的区别了么?

规则中多了:--rcheck --seconds 10800 

也就是说,从最后一个数据包开始不超过10800秒,数据包就会发送到与前一个数据包相同的目标链(pod)。否则,数据包被发送到一个随机链接(其它pod)。



四、Openshift SDN网络策略实验


在前面的实验中,OCP的OVS用的是ovs-multitenant。在本实验中,我们会使用 ovs-networkpolicy。


我们使用一个网络策略迁移脚本:migrate-network-policy.sh,让project完成从ovs-multitenant到 ovs-networkpolicy的转换。


https://raw.githubusercontent.com/openshift/origin/master/contrib/migration/migrate-network-policy.sh

执行脚本:

接下来,修改ansible配置文件,用redhat/openshift-ovs-networkpolicy替代 os_sdn_network_plugin_name,然后再次执行OCP安装脚本。


接下来,我们将部署整套应用来验证网络策略。应用架构如下:

前端服务提供UI,允许用户登录并显示所有注册用户用php编写的推文。  


电子邮件服务,可以将电子邮件发送给以Python编写的注册用户,将数据保存在MySQLdb中。


Twitter服务,用于为在Tomcat上运行的Java编写的注册用户提供推文。该服务由前端HTML直接调用。


用户注册后端注册用户,将注册用户保存在MongoDB中,并用Node.Js编写。该服务由前端HTML调用并执行用户注册。一旦用户注册,它会调用电子邮件服务发送电子邮件确认。


在本测试中,将会有三个OCP的project:


msclient project: 所有前端服务。

msservices project:user-registration 后端服 和 Twitter service.

msinfra project: 所有邮件服务。


接下来部署应用:

git clone https://github.com/newgoliath/microservices-on-openshift

oc new-project msclient

oc new-project msservices

oc new-project msinfra


修改1.setVariable.sh,在里面我设置了个人的谷歌邮箱:


source 2.deployEmailSvc-PythonMySQL.sh

source 3.deployTwitter-Tomcat.sh

source 4.deployUserRegBackend-NodejsMongo.sh

source 5.deployFrontend-PHP.sh


接下来,查看部署的应用:


通过浏览器访问route,可以显示出如下内容:


接下来,我们注册几个账户:


接下来,根据注册的用户,可以登录:

接下来,针对这套微服务,我们增加网络安全策略。


首先,我们让所有对msclient项目的网络请求都被拒绝。


再次访问浏览器:

此时loadbalance到pod是8080端口。

接下来,我们单独放开8080端口:


再次访问浏览器,可以访问了:





五、Openshift对计算资源管理


OCP对计算资源的管理,可以通过limits实现。同时配置HPA,已确保pod可以实现自动弹性伸缩。


创建HPA测试的项目和应用:

oc new-project test-hpa

oc new-app openshift/hello-openshift:v1.1.1.1 -n test-hpa

创建limits:


[root@master2 installscripts]# cat limits.json

{

    "kind": "LimitRange",

    "apiVersion": "v1",

    "metadata": {

        "name": "limits",

        "creationTimestamp": null

    },

    "spec": {

        "limits": [

            {

                "type": "Pod",

                "max": {

                    "cpu": "100m",

                    "memory": "750Mi"

                },

                "min": {

                    "cpu": "10m",

                    "memory": "5Mi"

                }

            },

            {

                "type": "Container",

                "max": {

                    "cpu": "100m",

                    "memory": "750Mi"

                },

                "min": {

                    "cpu": "10m",

                    "memory": "5Mi"

                },

                "default": {

                    "cpu": "50m",

                    "memory": "100Mi"

                }

            }

        ]

    }

}

配置HPA参数:


接下来,通过一个脚本对应用加压:

[root@master1 ~]# IP=$(oc get svc hello-openshift --template "{{ .spec.portalIP }}")[root@master1 ~]# for time in {1..15000}  do   echo time $time   curl ${IP}:8080  done


pod发生了自动扩容:




魏新宇

"大卫分享"运营者、红帽资深解决方案架构师

专注开源云计算、容器及自动化运维在金融行业的推广

拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、ITIL V3、Cobit5、C-STAR、AIX、HPUX等相关认证。



 
大卫分享 更多文章 干货分享:基于JBoss的七个Java应用场景 Openshift的高可用架构设计 深度分析:Istio替代Spring Cloud的合理性 六种开发环境部署大全:基于Openshift 基于Openshift部署七种开发环境:第一篇之FUSE、Vert.x、Spring Boot
猜您喜欢 勒索病毒爆发的前后,第 5 期技术微周刊出炉了 王胜江:现在是创投界最好的秋天! 万字干货|在高级产品经理眼中,好的项目管理流程是怎样的 Hackathon4.0圆满闭幕! 途牛APP首页代码优化重构实践