Skip to content
研发内网可能用到的组件,如Gerrit、GitLab、Jira、Confluence、DNS、Proxy、Nexus、Jenkins、Ldap等。
HTML Shell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
confluence Fix jira and confluence Jan 4, 2020
dns
gitlab
jira
ldap
nexus
nginx
proxy
sonarqube
.gitignore
README.md

README.md

[TOC]

目前的方案主要是围绕Gitlab及其自带的gitlab-runner在搭建,如图。

如果要查看基于Gerrit和Jenkins的部署方式,请切换到v0.1分支(其中各组件版本可能有点旧了,请自行使用镜像最新版本的镜像)。

以下工具基于 Docker & Docker Compose 来部署,其中的配置全部基于“example.com”,具体部署前可根据实际情况进行批量替换。

0 准备

0.1 安装docker

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

并根据需要配置国内源。

0.2 下载docker-compose

参考文档.

sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

0.2 开启IPv4 IP forward(不配置似乎也没事,待验证)

容器要想访问外部网络,需要本地系统的转发支持。编辑/etc/sysctl.conf,添加或修改:

net.ipv4.ip_forward=1

然后重启网络和docker。

systemctl restart network
systemctl restart docker

0.4 挂载目录的SELinux权限

这一版,容器数据的持久化数据的挂载有限使用命名卷,而不是直接将主机目录挂载到容器里。以便避免权限等问题导致的坑。

如果开启SELinux,并且采用目录挂载挂载的方式,需要配置SELinux权限。如挂载主机目录为/srv/mysql,则执行:

chcon -Rt svirt_sandbox_file_t /srv/mysql

0.4 防火墙方面

iptables增加端口

配置iptable规则:vi /etc/sysconfig/iptables

# 增加一行(如增加UDP 123端口)
-A INPUT -m state --state NEW -m udp -p udp --dport 123 -j ACCEPT

firewalld开通端口

firewall-cmd --zone=public --add-port=80/tcp --permanent
systemctl restart firewalld

1 部署节点

1.1 研发内网域名解析

研发内用的DNS有dnsmasq来提供,由nginx进行反向代理。DNS的docker-compose.yml如下:

services:
  dns:
    image: andyshinn/dnsmasq
    container_name: dns
    hostname: dns
    networks:
      - devops
    privileged: true
    cap_add:
      - NET_ADMIN
    ports:
      - "53:53"
      - "53:53/udp"
    volumes:
      - './etc_dnsmasq.conf:/etc/dnsmasq.conf'
      - './etc_resolv.dnsmasq:/etc/resolv.dnsmasq'
      - './etc_dnsmasq.hosts:/etc/dnsmasq.hosts'

容器的三个配置文件通过volume的方式与主机当前目录下的配置文件共享。

DNS服务使用的是dnsmasq。其中,

  • /etc/dnsmasq.conf是主配置文件,主要内容有两行:
# 指定配置外网DNS地址的resolv文件
resolv-file=/etc/resolv.dnsmasq
# 指定配置内网域名解析关系的文件
addn-hosts=/etc/dnsmasq.hosts
  • /etc/resolv.dnsmasq,配置外网DNS地址,内容如下:
nameserver 114.114.114.114
nameserver 202.106.0.20
  • /etc/dnsmasq.hosts,配置内网域名解析,内容如下:
# ops
172.31.0.254    dns ntp dns.example.com ntp.example.com
172.31.0.253    nas nas.example.com
172.31.3.101    vcenter vcenter.example.com

172.23.0.100    ldap ldap.example.com
172.23.0.101    jira jira.example.com

... ...

1.2 反向代理

平台由多个组件构成,涉及多个不同的IP和端口号,为了方便记忆,采用域名+反向代理的配置方式。反向代理用Nginx提供,docker-compose.yml如下:

services:
  nginx:
    image: nginx
    container_name: nginx
    hostname: nginx
    networks:
      - devops
#   dns:
#     - 172.31.0.254
    privileged: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./conf.d:/etc/nginx/conf.d	# 1
      - ./www:/var/www							# 2
      - ./ssl:/etc/nginx/ssl				# 3
  1. 所有的反向代理配置放在conf.d目录下,随着下面各个组件的介绍会继续补充;
  2. 静态页面放在www目录下;
  3. 证书放在ssl下。

1.3 LDAP

LDAP使用OpenLDAP进行维护,使用phpldapadmin管理界面。这一版的LDAP增加了SSL支持,因此需要提供证书。docker-compose.yml如下:

services:
  ldap:
    image: osixia/openldap
    container_name: ldap
    hostname: ldap
    networks:
      - devops
    ports:
      - "389:389"
      - "636:636"
    environment:
      - LDAP_ORGANISATION=ExampleCom
      - LDAP_DOMAIN=example.com
      - LDAP_ADMIN_PASSWORD=passwd
      - LDAP_READONLY_USER=true
      - LDAP_READONLY_USER_USERNAME=readonly
      - LDAP_READONLY_USER_PASSWORD=passwd
      - LDAP_TLS_CRT_FILENAME=ldap.example.com.crt		#1
      - LDAP_TLS_KEY_FILENAME=ldap.example.com.key		#1
      - LDAP_TLS_CA_CRT_FILENAME=root.example.com.crt	#1
    volumes:
      - ./ssl:/container/service/slapd/assets/certs		#1
      - ldap-var:/var/lib/ldap
      - ldap-etc:/etc/ldap/slapd.d
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"

  ldap-admin:
    image: osixia/phpldapadmin
    container_name: ldap-admin
    hostname: ldap-admin
    depends_on:
      - ldap
    networks:
      - devops
#   If nginx not on the same "devops" network, uncomment the following two lines.
#   ports:
#     - "8080:80"
#     - "8443:443"
    environment:
      - PHPLDAPADMIN_LDAP_HOSTS=ldap
      - PHPLDAPADMIN_HTTPS_CRT_FILENAME=ldap.example.com.crt				#1
      - PHPLDAPADMIN_HTTPS_KEY_FILENAME=ldap.example.com.key				#1
      - PHPLDAPADMIN_HTTPS_CA_CRT_FILENAME=root.example.com.crt			#1
    volumes:
      - ./ssl:/container/service/phpldapadmin/assets/apache2/certs	#1
      - ldap-admin:/var/www/phpldapadmin
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"
  1. 证书文件通过卷挂载,并使用环境变量进行指定。

1.4 JIRA & Confluence

以Jira为例,docker-compose.yml如下:

version: '3'

services:
  mysql-jira:
    image: mysql:5.7
    container_name: mysql-jira
    environment:
      - MYSQL_ROOT_PASSWORD=devops
      - MYSQL_DATABASE=jiradb				#1
      - MYSQL_USER=jira							#1
      - MYSQL_PASSWORD=devops				#1
    networks:
      - devops
    volumes:
      - ./mysql/mysqld_jira.cnf:/etc/mysql/conf.d/mysqld_jira.cnf		#3
      - mysql-jira:/var/lib/mysql
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"
  jira:
    image: atlassian/jira-software
    container_name: jira
    hostname: jira
    depends_on:
      - mysql-jira
    ports:
      - "8081:8080"
    environment:
      - JVM_MINIMUM_MEMORY=512m
      - JVM_MAXIMUM_MEMORY=2048m
      - ATL_PROXY_NAME=jira.example.com #2
      - ATL_PROXY_PORT=443							#2
      - ATL_TOMCAT_SCHEME=https					#2
      - ATL_TOMCAT_SECURE=true					#2
    networks:
      - devops
    volumes:
      - ./mysql/mysql-connector-java-5.1.48.jar:/opt/atlassian/jira/lib/mysql-connector-java-5.1.48.jar																#3
      - jira:/var/atlassian/application-data/jira
  1. 启动MySQL的时候即初始化好数据库和用户;
  2. Jira前方经过反向代理,而反向代理配置了SSL;
  3. Jira对数据库有编码的要求,./mysql/mysqld_jira.cnf中可见:
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_bin

Jira和Confluence的破解方法,仅用于学习,企业用户请购买正版。

1.5 Gitlab

1.5.1 让出22端口

注意,由于gitlab的SSH默认使用的是22端口,因此主机的sshd建议修改为其他端口。编辑/etc/ssh/sshd_config增加2222端口:

#Port 22
Port 2222

然后执行如下命令为SELinux开启2222端口:

semanage port -a -t ssh_port_t -p tcp 2222

然后执行如下命令让防火墙通过2222端口:

firewall-cmd --permanent --add-port=2222/tcp
systemctl restart firewalld.service

1.5.2 启动gitlab

使用gitlab官方docker镜像,docker-compose.yml文件如下:

services:
  gitlab:
    image: gitlab/gitlab-ce
    container_name: gitlab
    hostname: gitlab
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.example.com'	#1
        nginx['redirect_http_to_https'] = true		#1
    ports:
      - "2222:22"
      - "8080:80"
      - "8443:443"
    networks:
      - devops
    volumes:
      - gitlab-config:/etc/gitlab								#2
      - gitlab-logs:/var/log/gitlab							#2
      - gitlab-data:/var/opt/gitlab							#2
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"

  1. 由于gitlab前方有支持SSL的反向代理,external_url为用户使用的地址;此处GITLAB_OMNIBUS_CONFIG环境变量可用于提前给出任意gitlab.rb中的配置。

挂载目录如下:

主机目录 容器目录 内容
gitlab-data /var/opt/gitlab 应用数据
gitlab-logs /var/log/gitlab 日志
gitlab-config /etc/gitlab GitLab配置文件

1.5.3 gitlab与LDAP的集成

由于配置文件已经共享到宿主机,因此可以通过编辑gitlab-config卷中的gitlab.rb配置gitlab:

###! **remember to close this block with 'EOS' below**
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
  main: # 'main' is the GitLab 'provider ID' of this LDAP server
    label: 'LDAP'
    host: 'ldap.example.com'
    port: 389
    uid: 'cn'
    bind_dn: 'cn=admin,dc=example,dc=com'
    password: '<passwd of admin>'
    encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
    verify_certificates: true
    active_directory: false
    allow_username_or_email_login: true
    lowercase_usernames: true
    block_auto_created_users: false
    base: 'dc=example,dc=com'
    user_filter: ''
    ## EE only
    group_base: ''
    admin_group: ''
    sync_ssh_keys: false
EOS

然后执行如下命令使gitlab配置生效:

docker exec -it gitlab gitlab-ctl reconfigure

1.6 SonarQube

Sonarqube没有太多可解释的,与Jira或Confluence类似,就是典型的一个数据库+一个应用的部署方式,数据库启动时自动创建database和相应的用户的密码;SonarQube为官方镜像。

SonarQube中用到的插件可以到SonarQube插件库下载,并复制到sonar-extensions卷的plugins目录下,并重启使其生效。

1.7 Nexus

仍然采用容器的部署方式,采用官方镜像sonatype/nexus3

使用nginx进行反向代理,将不同的域名映射到不同的nexus端口或路径。

因此docker-compose.yml文件内容如下:

services:
  nexus:
    image: sonatype/nexus3
    container_name: nexus
    hostname: nexus
    networks:
      - devops
    ports:
      - "8081:8081"
    volumes:
     - nexus-data:/nexus-data

  registry:
    image: registry:2
    container_name: registry
    networks:
      - devops
    ports:
      - 5000:5000
    environment:
      - REGISTRY_PROXY_REMOTEURL="https://docker.mirrors.ustc.edu.cn"
    volumes:
      - registry:/var/lib/registry

1.8 上网代理

由于研发人员经常需要上Google,或查询各种技术官网资料,因此一个统一的上网代理还是有必要的。

这里使用SOCKS5来做外网的代理,支持PAC模式和全局代理模式。

  1. 代理使用sslocal,代理服务器的配置通过json文件传给该命令,端口为1080;
  2. sslocal的代理为socks协议,因此使用privoxy转为http协议,端口为8118,该代理地址可用于全局代理模式的配置;
  3. PAC代理模式维护一个list,只有list中的网址是走代理的,通过一个pac文件来维护,同时指定了SOCKS代理的地址,将该pac文件用http服务提供出来,使用者直接配置该pac文件的http地址即可使用PAC方式上网。

以上,第1,2由sgrio/alpine-sslocalproxy容器提供;第3条就起一个httpd容器,将pac文件用http访问即可。docker-compose.yml如下:

services:
  proxy:
    image: sgrio/alpine-sslocalproxy
    container_name: proxy
    hostname: proxy
    networks:
      - devops
    privileged: true
    ports:
      - "1080:1080"
      - "8118:8118"
    volumes:
      - './ss-client.json:/etc/shadowsocks-libev/config.json'    # 1
  1. 代理服务器的配置通过volume挂载ss-client.json文件实现。

PAC的支持

pac的内容放在nginx/www/pac中通过挂载到nginx的目录下,从而可以直接通过地址proxy.example.com/pac访问。

pac的生成通过gen-pac.sh命令生成,该命令会从gfwlist拉取一份常用的代理网站地址list,另外还会加上whitelist中自定义的list,生成pac文件index.html

代码中的代理配置信息(infra/ss-client.json)无效。

You can’t perform that action at this time.