基于consul实现nginx的动态upstream

1. 相关组件

未分类

consul下载地址 https://releases.hashicorp.com/consul/1.0.6/consul_1.0.6_linux_amd64.zip

nginx-upsync-module下载地址 https://github.com/weibocom/nginx-upsync-module/archive/nginx-upsync-1.8.x.zip

nginx下载地址 http://nginx.org/download/nginx-1.8.0.tar.gz

2. 简单Demo

2.1 安装并配置Consul

# 解压包
unzip consul_1.0.6_linux_amd64.zip
# 移动consul到格式位置
mv consul /root/services/account_consul/
# 启动consul
/root/services/account_consul/consul agent -server -bootstrap-expect=1 -data-dir=/root/data/consul/ -node=accounting01 -bind=172.31.132.207 -config-dir=/root/data/consul_config/ -client 0.0.0.0 -ui
# 添加upstreams配置
curl -X PUT http://172.31.132.207:8500/v1/kv/upstreams/accounting/127.0.0.1:8000
curl -X PUT http://172.31.132.207:8500/v1/kv/upstreams/accounting/127.0.0.1:8001

访问http://ip:8500/ui/

未分类

上图我们可以看出,我们已经通过http请求存储了upstreams配置信息, 接下来我们需要让Nginx从consul自动更新upstreams配置;

2.2 重新编译安装Nginx,添加upsync模块

2.2.1 install

# 解压
tar -zxvf nginx-1.8.0.tar.gz
unzip nginx-upsync-1.8.x.zip
# 编译安装
cd nginx-1.8.0
./configure   --prefix=/usr/local/nginx     --with-pcre  --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_realip_module --with-http_sub_module  --add-module=/root/packages/nginx-upsync-module-nginx-upsync-1.8.x
make && make install
# 检查Nginx是否按照成功
/usr/local/nginx/sbin/nginx

2.2.2 config

vim /usr/local/nginx/conf/nginx.conf
# 修改用户
(PS:由于我是root环境启动的服务, 若Nginx的用户不是root的话, 某些文件无法访问, 例如: 静态文件)
user  root; 
# 添加额外配置文件路径
(PS: 非必须, 但是我习惯这么做)
http {
    ...
    include /usr/local/nginx/conf/sites-enabled/*;
    server {
    ....
    }
}
# 添加Nginx的upstream配置
(accouting_server) ➜  conf cd sites-enabled
(accouting_server) ➜  sites-enabled pwd
/usr/local/nginx/conf/sites-enabled
(accouting_server) ➜  sites-enabled ll
total 8.0K
-rw-r--r-- 1 root root 915 Feb 24 18:13 accounting
-rw-r--r-- 1 root root 213 Feb 24 18:13 consul
(accouting_server) ➜  sites-enabled cat accounting
upstream accounting {
    server 127.0.0.1:11111;
    upsync 172.31.132.207:8500/v1/kv/upstreams/accounting/ upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
    upsync_dump_path /usr/local/nginx/conf/servers/accounting.conf;
}
server {
    listen 80;
    #server_name accounting.willdx.me;
    server_name 47.104.93.126
    charset    utf-8;
    client_max_body_size    20M;
    access_log    /var/log/nginx/accounting/access.log;
    error_log    /var/log/nginx/accounting/error.log;
    location /media  {
        alias /root/mycode/accouting_server/accouting_project/media;
    }
    location /static {
        alias /root/mycode/accouting_server/accouting_project/static;
    }
    location / {
        #proxy_set_header Host $host;
        #proxy_pass http://localhost:8888/;
        #proxy_redirect http://0.0.0.0:8888/ /;
        proxy_pass http://accounting;
    }
}

2.2.3 测试

# 启动测试服务
python -m http.server 8000
python -m http.server 8001

测试1: 负载均衡

# 测试
for i in `seq 10000`; do curl http://47.104.93.126/; sleep 1; done;
# 发现请求是负载均衡的

测试2: 测试动态的更改数据之后Nginx请求

# 删除一个配置
curl -X DELETE  http://172.31.132.207:8500/v1/kv/upstreams/accounting/127.0.0.1:8000
true#
# 再次测试2.2.3步骤
发现请求不走127.0.0.1:8000了
# 开启8000
curl -X PUT  http://172.31.132.207:8500/v1/kv/upstreams/accounting/127.0.0.1:8000
# 再次测试2.2.3步骤
发现请求又走127.0.0.1:8000了

2.3 Demo小结

我们可以consul来进行集中的配置管理, 服务变更的时候, 我们只需要更改配置即可;

CentOS 7简单的利用yum源安装Nginx

未分类

项目需求要使用80端口部署静态html5的官网,为了稳定高效和后续的扩充,故使用轻巧又强大的Nginx来作80端口的服务器。
  
下面就简单介绍一下简单的利用yum源安装Nginx,并申请阿里云免费提供的的SymantecSSL证书,来开启SSL加密的443端口https。

安装环境:CentOS7 64位 Minimal版(VMware)

配置网卡

使用桥接,开启网卡并设置:静态ip、网关、子网掩码、DNS

# 编辑网卡配置
vi /etc/sysconfig/network-scripts/ifcfg-eno16777736

未分类

TYPE=Ethernet
BOOTPROTO=static
IPADDR=192.168.0.200
GATEWAY=192.168.0.1
NETMASK=255.255.255.0
DNS1=192.168.0.1
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno16777736
UUID=11b992a7-1630-4a26-bd62-8ce65e3e5c78
DEVICE=eno16777736
ONBOOT=yes
# 重启网络服务
systemctl restart network
# 查看ip
ip addr

配置防火墙

http协议默认端口为80端口,SSL加密的https协议的默认端口为443端口。
远程访问,需要打开防火墙。CentOS 7 中默认防火墙是firewalld,默认为关闭状态。

# 启动Firewall
systemctl start firewalld
# 设置开机自启动
systemctl enable firewalld
# 开放http80端口
firewall-cmd --permanent --add-port=80/tcp
# 开放https443端口
firewall-cmd --permanent --add-port=443/tcp
# 重载防火墙配置
firewall-cmd --reload

# 查看所有已开放端口
firewall-cmd --list-ports

# 若无firewall-cmd命令则先安装firewalld
yum install firewalld -y

先安装nginx的yum源
http://nginx.org/en/linux_packages.html#stable 找到链接,安装:

rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

未分类

查看:

yum info nginx

未分类

安装:

yum install nginx

未分类

安装完成后nginx就已经启动了,可以查看进程:

ps -ef | grep nginx

未分类

如果一切进展顺利的话,现在你可以通过你的域名或IP来访问你的Web页面来预览一下Nginx的默认页面

未分类

如果看到这个页面,那么说明你的CentOS 7 中 web服务器已经正确安装。

开机自启:

systemctl enable nginx

Nginx配置信息

# 网站文件存放默认目录
/usr/share/nginx/html
# 网站默认站点配置
/etc/nginx/conf.d/default.conf
# 自定义Nginx站点配置文件存放目录
/etc/nginx/conf.d/
# Nginx全局配置
/etc/nginx/nginx.conf

启动nginx:

systemctl start nginx

Nginx手动启动

nginx -c nginx.conf

在这里你可以改变设置用户运行Nginx守护程序进程一样,和工作进程的数量得到了Nginx正在运行,等等。

据运维同学反馈,通过yum源安装之后,在安装插件时会有所限制。但针对目前学习,已经足够了。

kubernetes下的Nginx加Tomcat三部曲之三:实战扩容和升级

本章是《kubernetes下的Nginx加Tomcat三部曲系列》的终篇,今天咱们一起在kubernetes环境对下图中tomcat的数量进行调整,再修改tomcat中web工程的源码,并将现有的tomcat的pod全部替换成新代码构建的结果:

未分类

往期章节

  1. kubernetes下的Nginx加Tomcat三部曲之一: http://devops.webres.wang/2018/02/kubernetes%E4%B8%8B%E7%9A%84nginx%E5%8A%A0tomcat%E4%B8%89%E9%83%A8%E6%9B%B2%E4%B9%8B%E4%B8%80%EF%BC%9A%E6%9E%81%E9%80%9F%E4%BD%93%E9%AA%8C/
  2. kubernetes下的Nginx加Tomcat三部曲之二: http://devops.webres.wang/2018/02/kubernetes%E4%B8%8B%E7%9A%84nginx%E5%8A%A0tomcat%E4%B8%89%E9%83%A8%E6%9B%B2%E4%B9%8B%E4%BA%8C%EF%BC%9A%E7%BB%86%E8%AF%B4%E5%BC%80%E5%8F%91/

列举步骤

  1. 在线扩容Tomcat;
  2. 验证扩容结果;
  3. 修改web工程源码;
  4. 构建web工程的新镜像;
  5. 让kubernetes的机器用上web工程的Docker镜像
  6. 在线更新Tomcat的pod的镜像;
  7. 验证更新结果;
  8. Nginx&Tomcat方式和SpringCloud方式扩容对比;

kubernetes环境基本情况

  1. 一个master,一个node;
  2. master的IP地址:192.168.119.148;
  3. node1的IP地址:192.168.119.153;

在线扩容Tomcat

  • 在装好kubectl工具的机器上执行kubectl get pods,查看当前pod情况:
root@master:~# kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
ng-59b887b8bc-jzcv5           1/1       Running   3          2d
tomcathost-7f68566795-8pl29   1/1       Running   3          2d
tomcathost-7f68566795-mvg5f   1/1       Running   3          2d
tomcathost-7f68566795-trscg   1/1       Running   3          2d

如上所示,目前是三个tomcat的pod;

  • 执行扩容命令kubectl scale deployment tomcathost –replicas=5,将tomcat的pod从3个增加到5个,如下:
root@master:~# kubectl scale deployment tomcathost --replicas=5
deployment "tomcathost" scaled
root@master:~# kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
ng-59b887b8bc-jzcv5           1/1       Running   3          2d
tomcathost-7f68566795-8kf76   1/1       Running   0          18s
tomcathost-7f68566795-8pl29   1/1       Running   3          2d
tomcathost-7f68566795-mvg5f   1/1       Running   3          2d
tomcathost-7f68566795-tp5xp   1/1       Running   0          18s
tomcathost-7f68566795-trscg   1/1       Running   3          2d

tomcat的pod已经增加到5个了,创建时间都只有18秒;

  • 去dashboard页面看以下tomcathost这个deployment的详情,可以看到tomcat数量已经上升到5个了,扩容成功:

未分类

点击上图红框1,再点击tomcathost这个服务,可以看到上图中的详情;
上图红框2中是5个tomcat的pod的容器IP地址;
点击上图红框3中的每个容器名,可以查看容器详情;
上图红框4显示了刚才的扩容事件;

验证扩容结果

nginx服务所在的node机器的IP地址是192.168.119.153,所以在浏览器上访问:http://192.168.119.153:30006/getserverinfo,反复刷新此页面,看到返回的IP地址在不断的更新,都是tomcat所在pod的IP地址,5个都会出现,如下图:

未分类

扩容实战就到这里,接下来我们修改web工程的源码,验证在线升级的能力;

修改web工程源码

tomcat上运行的web工程源码,可以GitHub下载,地址和链接信息如下表所示:

未分类

这个git项目中有多个目录,本次的web工程源码放在k8stomcatdemo,如下图红框所示:

未分类

  • 打开工程中的ServerInfo.java,web接口的源码如下:
@RequestMapping(value = "/getserverinfo", method = RequestMethod.GET)
    public String getUserInfoWithRequestParam(){
        return String.format("server : %s, time : %s", getIPAddr(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
  • 修改返回的字符串内容,在前面加上”From new version,”:
@RequestMapping(value = "/getserverinfo", method = RequestMethod.GET)
    public String getUserInfoWithRequestParam(){
        return String.format("From new version, server : %s, time : %s", getIPAddr(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

构建web工程的新镜像

修改pom.xml中的工程版本,从0.0.1-SNAPSHOT改为0.0.3,如下所示:

<groupId>com.bolingcavalry</groupId>
    <artifactId>k8stomcatdemo</artifactId>
    <version>0.0.3</version>
    <packaging>jar</packaging>
    <name>k8stomcatdemo</name>
  • 在pom.xml所在目录执行mvn clean package -DskipTests docker:build,会编译构建工程,并且在本地制作好镜像文件,如下:
root@maven:/usr/local/work/k8s/k8stomcatdemo# docker images
REPOSITORY                                              TAG                 IMAGE ID            CREATED             SIZE
bolingcavalry/k8stomcatdemo                             0.0.3               5f2d27eafd1b        17 seconds ago      658 MB
bolingcavalry/k8stomcatdemo                             latest              5f2d27eafd1b        17 seconds ago      658 MB

让kubernetes的机器用上web工程的Docker镜像

现在的镜像只存在于开发和构建web工程的电脑上,为了让kubernetes的node机器能用上这个镜像,可以用以下几种方式实现:

1、用docker push命令将本机镜像推送到hub.docker.com网站,这样其他机器都可以通过docker pull命令取得了,我就是用的这种方法,需要在hub.docker.com上注册,下图是正在push中:

未分类

2、用docker save命令导出镜像文件,再用docker load命令导入;
3、kubernetes所在机器安装java和maven环境,将工程在这里编译构建;
4、使用docker私有仓库,例如搭建局域网私有仓库或者阿里云私有仓库,参考 http://blog.csdn.net/boling_cavalry/article/details/78934391

在线更新Tomcat的pod的镜像

  • 在kubernetes上执行以下命令,即可升级镜像,当前的5个tomcat的pod会被销毁,然后用新的镜像创建pod:
kubectl set image deployment/tomcathost tomcathost=bolingcavalry/k8stomcatdemo:0.0.3
  • 控制台提示的信息如下:
root@maven:/usr/local/work/k8s/k8stomcatdemo# kubectl set image deployment/tomcathost tomcathost=bolingcavalry/k8stomcatdemo:0.0.3
deployment "tomcathost" image updated
  • 此刻反复执行kubectl get pod,会看到新容器创建,旧容器正在被销毁,如下:
root@maven:/usr/local/work/k8s/k8stomcatdemo# kubectl get pod
NAME                          READY     STATUS              RESTARTS   AGE
ng-59b887b8bc-jzcv5           1/1       Running             3          2d
tomcathost-6dfc87dc8b-9bkfv   1/1       Running             0          50s
tomcathost-6dfc87dc8b-h6gx4   0/1       ContainerCreating   0          50s
tomcathost-6dfc87dc8b-ht2d8   1/1       Running             0          18s
tomcathost-6dfc87dc8b-pfb56   1/1       Running             0          10s
tomcathost-6dfc87dc8b-x8pnn   1/1       Running             0          14s
tomcathost-7f68566795-8pl29   0/1       Terminating         3          2d
tomcathost-7f68566795-trscg   0/1       Terminating         3          2d

验证更新结果

  • nginx服务所在的node机器的IP地址是192.168.119.153,所以在浏览器上访问:http://192.168.119.153:30006/getserverinfo,可以看到”From new version”这个字符串,如下图:

未分类

去dashboard页面看服务详情,可以看见一系列的缩容和扩容事件,如下图:

未分类

Nginx&Tomcat方式和SpringCloud方式扩容对比

在之前的文章中,我们实战了SpringCloud环境下服务提供方的扩容,由于是“注册&发现”的方式,扩容只需要往SpringCloud环境添加provider机器,不需要做什么设置,请求就会被落到新的provider上,相关实战的地址如下:

  1. Docker下的Spring Cloud三部曲之一: http://blog.csdn.net/boling_cavalry/article/details/79177930

  2. Docker下的Spring Cloud三部曲之二: http://blog.csdn.net/boling_cavalry/article/details/79134497

  3. Docker下的Spring Cloud三部曲之三: http://blog.csdn.net/boling_cavalry/article/details/79192376

在Nginx加Tomcat环境中,如果不是在kubernetes环境,我们增加Tomcat之后需要修改Nginx配置,否则到达Nginx的请求不会被转发到新的机器上去,幸运的是kubernete帮我们解决了这个问题,扩容缩容都只需要控制副本数即可,不用修改Nginx配置了;

doceker-compose虽然可以修改副本数,但是Nginx的配置仍然需要修改,否则新创建的Tomcat容器都有自己的IP地址,Nginx还是感知不到;

至此,kubernetes下的Nginx加Tomcat三部曲就全部结束了,希望能在您的kubernetes实战中有所帮助;

kubernetes下的Nginx加Tomcat三部曲之二:细说开发

本文是《kubernetes下的Nginx加Tomcat三部曲》的第二章,在 http://devops.webres.wang/2018/02/kubernetes%E4%B8%8B%E7%9A%84nginx%E5%8A%A0tomcat%E4%B8%89%E9%83%A8%E6%9B%B2%E4%B9%8B%E4%B8%80%EF%BC%9A%E6%9E%81%E9%80%9F%E4%BD%93%E9%AA%8C/ 一文我们快速部署了Nginx和Tomcat,达到以下效果:

未分类

本文我会详细说明在kubernetes部署上述网络服务时,需要做哪些具体的工作;

列举步骤

需要以下操做才能在kubernetes上部署Nginx加Tomcat的服务:

  1. 开发Tomcat上的web工程和Docker镜像;
  2. 让kubernetes的机器用上web工程的Docker镜像;
  3. 开发Tomcat对应的deployment脚本;
  4. 开发Tomcat对应的service脚本;
  5. 开发Nginx对应的Docker镜像;
  6. 让kubernetes的机器用上Nginx的Docker镜像
  7. 开发Nginx对应的deployment脚本;
  8. 开发Nginx对应的service脚本;
  9. 开发启动上述pod和service的脚本;
  10. 开发停止并清除上述pod和service的脚本

脚本文件下载

本次体验所需的deployment和service资源是通过脚本创建的,这个脚本可以通过以下两种方式中的任意一种下载:

  1. CSDN下载(无法设置免费下载,只能委屈您用掉两个积分了):http://download.csdn.net/download/boling_cavalry/10235034
  2. GitHub下载,地址和链接信息如下表所示:

未分类

这个git项目中有多个目录,本次所需的资源放在k8s_nginx_tomcat_resource,如下图红框所示:

未分类

下到的k8stomcatcluster20180201.tar是个压缩包,复制到可以执行kubectl命令的ubuntu电脑上,然后解压开,是个名为k8stomcatcluster的文件夹;

Spring boot的web工程源码下载

GitHub下载,地址和链接信息如下表所示:

未分类

这个git项目中有多个目录,本次的web工程源码放在k8stomcatdemo,如下图红框所示:

未分类

接下来我们开始实战开发吧;

开发环境

本次实战开发环境的具体信息如下:

  1. 操作系统:Ubuntu16;
  2. Docker版本:17.03.2-ce;
  3. JDK:1.8.0_151;
  4. maven:3.3.3;

Tomcat上的web工程和Docker镜像

web工程用来提供http服务,返回当前机器的IP地址给浏览器,完整源码请参照前面下载的k8stomcatdemo工程,这里我们还是重新创建一次;

1、创建一个springboot工程,pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bolingcavalry</groupId>
    <artifactId>k8stomcatdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>k8stomcatdemo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <!--新增的docker maven插件-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.12</version>
                <!--docker镜像相关的配置信息-->
                <configuration>
                    <!--镜像名,这里用工程名-->
                    <imageName>bolingcavalry/${project.artifactId}</imageName>
                    <!--TAG,这里用工程版本号-->
                    <imageTags>
                        <imageTag>${project.version}</imageTag>
                    </imageTags>
                    <!--镜像的FROM,使用java官方镜像-->
                    <baseImage>java:8u111-jdk</baseImage>
                    <!--该镜像的容器启动后,直接运行spring boot工程-->
                    <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
                    <!--构建镜像的配置信息-->
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

可以看到这是个普通的springboot的web工程,唯一不同的是多了一个maven插件:docker-maven-plugin,使用该插件我们可以将maven工程制作成docker镜像;

2、整个工程只有一个Controller,开通一个http接口,将当前服务器IP地址返回,源码如下:

@RestController
public class ServerInfo {

    @RequestMapping(value = "/getserverinfo", method = RequestMethod.GET)
    public String getUserInfoWithRequestParam(){
        return String.format("server : %s, time : %s", getIPAddr(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    /**
     * 获取本机IP地址
     * @return
     */
    private static String getIPAddr(){
        String hostAddress = null;
        try{
            InetAddress address = InetAddress.getLocalHost();
            hostAddress = address.getHostAddress();
        }catch (UnknownHostException e){
            e.printStackTrace();
        }

        return hostAddress;
    }
}

以上就是工程的关键源码;

3、在pom.xml所在目录执行mvn clean package -DskipTests docker:build,会编译构建工程,并且在本地制作好镜像文件,如下:

root@maven:/usr/local/work/github/blog_demos# docker images
REPOSITORY                                              TAG                 IMAGE ID            CREATED             SIZE
bolingcavalry/k8stomcatdemo                             latest              1d41d9980a0b        43 hours ago        658 MB
bolingcavalry/k8stomcatdemo                             0.0.1-SNAPSHOT      c91bc368a729        46 hours ago        658 MB

想了解更多maven制作docker镜像的细节,请看 http://blog.csdn.net/boling_cavalry/article/details/78872020

让kubernetes的机器用上web工程的Docker镜像

现在的镜像只存在于开发和构建web工程的电脑上,为了让kubernetes的node机器能用上这个镜像,可以用以下几种方式实现:

  1. 用docker push命令将本机镜像推送到hub.docker.com网站,这样其他机器都可以通过docker pull命令取得了,我就是用的这种方法,需要在hub.docker.com上注册;
  2. 用docker save命令导出镜像文件,再用docker load命令导入;
  3. kubernetes所在机器安装java和maven环境,将工程在这里编译构建;
  4. 使用docker私有仓库,例如搭建局域网私有仓库或者阿里云私有仓库,参考 http://blog.csdn.net/boling_cavalry/article/details/78934391

Tomcat对应的deployment脚本

用yaml文件将详情配置好,再用kubectl命令执行这个配置就能创建pod,这个web应用镜像的配置文件名为tomcat.yaml,内容如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcathost
spec:
  replicas: 3
  template:
    metadata:
     labels:
       name: tomcathost
    spec:
     containers:
     - name: tomcathost
       image: bolingcavalry/k8stomcatdemo:0.0.1-SNAPSHOT
       tty: true
       ports:
       - containerPort: 8080

将上述脚本的几个关键点列举一下:

  1. version用extensions/v1beta1;
  2. kind用Deployment,支持升级镜像和滚动升级;
  3. 使用的镜像bolingcavalry/k8stomcatdemo:0.0.1-SNAPSHOT,是我从本地push到hub.docker.com上去的;
  4. 创建的容器对外暴露了8080端口;

Tomcat对应的service脚本

创建了tomcat的pod之后,为了能在kubernetes环境中给其他service使用,需要将这些pod包装为service,这里是通过tomcat-svc.yaml文件来配置的,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: tomcathost
spec:
  type: ClusterIP
  ports:
       - port: 8080
  selector:
    name: tomcathost

将上述脚本的几个关键点列举一下:

  1. 服务对应的pod是tomcathost;
  2. type用ClusterIP,为内部service调用提供统一IP地址;
  3. 服务对外暴露了pod的8080端口;

Nginx对应的Docker镜像

  • 定制的Nginx镜像和Nginx官方镜像相比,唯一的区别就是nginx.conf文件不同,我们用的nginx.conf内容如下:
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    #include /etc/nginx/conf.d/*.conf;

    upstream tomcat_client {
         server tomcathost:8080;
    } 

    server {
        server_name "";
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        location / {
            proxy_pass http://tomcat_client;
            proxy_redirect default;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

以上配置中,新增的upstream对应的IP地址是tomcathost,这是tomcat的service名称,在Nginx运行的时候,通过tomcathost就能访问到tomcat的Pod;

  • 制作Docker镜像的Dockerfile文件内容如下,每行都有注释就不再多说了:
# First docker file from bolingcavalry
# VERSION 0.0.1
# Author: bolingcavalry

#基础镜像
FROM nginx:stable

#作者
MAINTAINER BolingCavalry <[email protected]>

#定义工作目录
ENV WORK_PATH /etc/nginx

#定义conf文件名
ENV CONF_FILE_NAME nginx.conf

#删除原有配置文件
RUN rm $WORK_PATH/$CONF_FILE_NAME

#复制新的配置文件
COPY ./$CONF_FILE_NAME $WORK_PATH/

#给shell文件赋读权限
RUN chmod a+r $WORK_PATH/$CONF_FILE_NAME

将nginx.conf和Dockerfile放在同一个目录,然后执行命令docker build -t bolingcavalry/nginx-with-tomcat-host:0.0.1 .,就能构建镜像文件了,如下:

root@maven:/usr/local/work/nginx# docker build -t bolingcavalry/nginx-with-tomcat-host:0.0.1 .
Sending build context to Docker daemon 14.51 MB
Step 1/7 : FROM nginx:stable
 ---> dfe062ee1dc8
Step 2/7 : MAINTAINER BolingCavalry <[email protected]>
 ---> Using cache
 ---> 93f4bf154c55
Step 3/7 : ENV WORK_PATH /etc/nginx
 ---> Using cache
 ---> d0158757fc9c
Step 4/7 : ENV CONF_FILE_NAME nginx.conf
 ---> Using cache
 ---> 7a18a8b417d6
Step 5/7 : RUN rm $WORK_PATH/$CONF_FILE_NAME
 ---> Using cache
 ---> f6f27d25539d
Step 6/7 : COPY ./$CONF_FILE_NAME $WORK_PATH/
 ---> Using cache
 ---> 33075a2b0379
Step 7/7 : RUN chmod a+r $WORK_PATH/$CONF_FILE_NAME
 ---> Using cache
 ---> 58ce530e160b
Successfully built 58ce530e160b

让kubernetes的机器用上Nginx的Docker镜像

这一步和之前的web工程的镜像放到kubernetes一样,有多种方式,我用的还是通过docker push推送到hub.docker.com网站,再在kubernetes上pull下来;

Nginx对应的deployment脚本

用yaml文件将详情配置好,再用kubectl命令执行这个配置就能创建pod,这个web应用镜像的配置文件名为nginx.yaml,内容如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: ng
spec:
  replicas: 1
  template:
    metadata:
     labels:
      name: ng
    spec:
     containers:
     - name: ng
       image: bolingcavalry/nginx-with-tomcat-host:0.0.1
       ports:
       - containerPort: 80

以上配置中有几点要注意:

  1. 使用镜像是刚才创建的nginx镜像bolingcavalry/nginx-with-tomcat-host:0.0.1;
  2. pod容器创建后,对外暴露80端口;

Nginx对应的service脚本

通过service定义的yaml文件nginx-svc.yam,将前面创建的nginx的pod包装为service:

apiVersion: v1
kind: Service
metadata:
  name: ng
spec:
  type: NodePort
  ports:
       - port: 80
         nodePort: 30006
  selector:
    name: ng

以上配置中有几点要注意:

  1. type使用NodePort,这样可以通过节点机器的IP访问此service;
  2. 将节点机器的30006端口和pod的80端口绑定,因此,外部访问节点IP+30006端口就能访问到此Nginx服务了;

启动上述pod和service的脚本

接下来我们创建一个shell脚本start_all.sh,将上述的tomcat和nginx的pod以及service全部创建和启动:

kubectl create -f tomcat.yaml
kubectl create -f tomcat-svc.yaml
kubectl create -f nginx.yaml
kubectl create -f nginx-svc.yaml
echo ""
echo "nginx and tomcat running now"

如上所示,通过kubectl create -f加文件名,就能创建好yaml文件中定义的pod和service;

停止并清除上述pod和service的脚本

创建一个shell脚本stop_all.sh,能够将上述的tomcat和nginx的pod以及service全部清除掉:

kubectl delete service tomcathost
kubectl delete deployment tomcathost
kubectl delete service ng
kubectl delete deployment ng
echo "nginx and tomcat stop now"

如上所示,其实就是通过kubectl delete命令将指定的pod和service资源删除;

以上就是在kubernetes搭建整个Nginx加Tomcat环境的所有资源,您就可以用这些像 http://devops.webres.wang/2018/02/kubernetes%E4%B8%8B%E7%9A%84nginx%E5%8A%A0tomcat%E4%B8%89%E9%83%A8%E6%9B%B2%E4%B9%8B%E4%B8%80%EF%BC%9A%E6%9E%81%E9%80%9F%E4%BD%93%E9%AA%8C/ 文中那样去搭建和体验kubernetes下的Nginx加Tomcat;

下一章,我们会在此环境的基础上实战Tomcat服务的扩容,并修改web工程的代码,再创建新的镜像,并且将kubernetes环境下在线升级新的web工程服务;

kubernetes下的Nginx加Tomcat三部曲之一:极速体验

章节介绍

在生产环境中,常用到Nginx加Tomcat的部署方式,如下图:

未分类

从本章开始,我们来实战kubernetes下部署上述Nginx和Tomcat服务,并开发spring boot的web应用来验证环境,整个实战分为以下三篇内容:

  1. 极速体验kubernetes下的nginx加tocmat;
  2. 细说nginx和tomcat镜像的制作;
  3. 实战tomcat server的在线扩容和应用升级;

实战工程介绍

本次实战创建的Pod如下:

  1. 一个Nginx的Pod,负责转发web请求到Tomcat;
  2. 三个Tomcat的Pod,上面部署了web应用,收到Nginx转发的请求后,返回的内容是当前Pod的IP地址;

准备kubernetes环境

本次实战需要可用的kubernetes环境,您可以参考以下文章进行快速搭建:

  1. http://blog.csdn.net/boling_cavalry/article/details/78762829
  2. http://blog.csdn.net/boling_cavalry/article/details/78764915

如何执行kubectl命令

实战中,需要在一台ubuntu电脑上安装kubectl工具,然后连接到kubernetes环境执行各种命令,kubectl工具的安装步骤可以参照这篇文章: http://blog.csdn.net/boling_cavalry/article/details/79223091

脚本文件下载

本次体验所需的deployment和service资源是通过脚本创建的,这个脚本可以通过以下两种方式中的任意一种下载:

  1. CSDN下载(无法设置免费下载,只能委屈您用掉两个积分了):http://download.csdn.net/download/boling_cavalry/10235034
  2. GitHub下载,地址和链接信息如下表所示:

未分类

这个git项目中有多个目录,本次所需的资源放在k8s_nginx_tomcat_resource,如下图红框所示:

未分类

下到的k8stomcatcluster20180201.tar是个压缩包,复制到可以执行kubectl命令的ubuntu电脑上,然后解压开,是个名为k8stomcatcluster的文件夹;

执行脚本文件下载

  1. 进入解压好的k8stomcatcluster目录;
  2. 执行命令chmod a+x *.sh,给shell脚本赋可执行权限;3.
    执行命令start_all.sh,创建本次实战的资源,页面输出如下信息:
root@maven:/usr/local/work/k8s/k8stomcatcluster# ./start_all.sh 
deployment "tomcathost" created
service "tomcathost" created
deployment "ng" created
service "ng" created

nginx and tomcat running now

验证服务已经启动

  • 先去kubernetes的管理页面看一下服务是否启动,如下图,名为ng、tomcathost的两个服务都已经启动:

未分类

  • 点击tomcathost服务,看到详情信息,里面有pod的情况,如下图:

未分类

  • 上图中显示tomcathost是在node1创建的,我的node1机器的IP地址是192.168.119.153,所以在浏览器输入:
    http://192.168.119.153:30006/getserverinfo

  • 在浏览器看到的信息如下图所示,机器Tomcat所在机器的IP地址和当前时间:

未分类

  • 多次刷新页面,能看到这三个IP地址:10.42.38.128、10.42.184.35、10.42.127.135,这就是三个Tomcat Pod的地址,Pod信息如下图红框所示:

未分类

  • 执行k8stomcatcluster目录下的stop_all.sh脚本,可以将前面创建的所有service,deployment资源删除;

  • 至此,我们已经在kubernetes下简单体验了Nginx加Tomcat的网站结构,接下来的章节,我们一起来细看如何在kubernetes下创建整个环境;

Docker nginx 反向代理设置

缘起

最近在公司搭建了一个基于 Gogs 的代码管理系统,以及基于 Kanboard 的任务管理系统等几个内部系统。由于部署在同一台机器上,基于不同的端口区分不同的服务。比如:

  • Git 服务 http://10.10.1.110:10080
  • 任务管理系统http://10.10.1.110:8888
  • 其他

为了更好的使用,通过内部域名区分,比如 :

  • Git 服务 http://gogs.vking.io
  • 任务管理系统 http://task.vking.io
  • 其他

注:vking.io 是内部域名,可通过 dnsmasq (http://www.thekelleys.org.uk/dnsmasq/doc.html) 配置。

方案一

现有服务都是通过 Docker 部署,nginx 同样通过 Docker 部署,使用官方提供的镜像即可。

  • 新建 nginx 配置文件, nginx.conf,存放路径为 /srv/docker/nginx/nginx.conf
# user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
# daemon off;
  • 新建反向代理设置文件 reverse-proxy.conf,存放路径为 /srv/docker/nginx/conf.d/reverse-proxy.conf
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
  default $http_x_forwarded_port;
  ''      $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
  default upgrade;
  '' close;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
  default off;
  https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent"';
access_log off;

# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
    server_name _; # This is just an invalid value which will never trigger on a real hostname.
    listen 80;
    access_log /var/log/nginx/access.log vhost;
    return 503;
}

# gogs.vking.io
upstream gogs.vking.io {
    # gogs
    server gogs:3000;
}

server
{
    server_name gogs.vking.io;
    listen 80;

    location / {
        proxy_pass http://gogs.vking.io;
    }
    access_log /var/log/nginx/access.log vhost;
}

# task.vking.io
upstream task.vking.io {
    # kanboard
    server kanboard:80;
}

server
{
    server_name task.vking.io;
    listen 80;

    location / {
        proxy_pass http://task.vking.io;
    }
    access_log /var/log/nginx/access.log vhost;
}

gogs 启动命令

docker container run -d --name gogs 
    --restart always 
    -p 10022:22  
    -p 10080:3000 
    --network gogs-net 
    -v /srv/docker/gogs:/data 
    gogs/gogs:latest

注: upstream gogs.vking.io 中的 server 中的 gogs:3000 分别指容器名称和原始expose 的端口。

  • 启动容器
docker container run -d --name nginx 
    --restart always 
    -p 80:80 
    --network gogs-net 
    -v /srv/docker/nginx/nginx.conf:/etc/nginx/nginx.conf 
    -v /srv/docker/nginx/conf.d:/etc/nginx/conf.d 
    nginx:alpines

注:–network gogs-net 指定三个容器在同一网络,如果用默认的 bridge的话,不需要设置

方案二

因为这些服务都是部署在一台机器上的,可以通过 Docker 的自动服务发现部署,原理见此。

  • gogs
docker container run -d --name gogs 
    --restart always 
    -p 10022:22  -p 10080:3000 
    --network gogs-net 
    -e VIRTUAL_HOST=gogs.vking.io 
    -e VIRTUAL_PORT=3000 
    -v /opt/docker/gogs:/data 
    gogs/gogs:latest
  • Kanboard
docker container run -d --name kanboard 
    --restart always 
    -p 8888:80 
    --network gogs-net 
    -e VIRTUAL_HOST=task.vking.io 
    -e VIRTUAL_PORT=80 
    -v /srv/docker/kanboard/data:/var/www/app/data 
    -v /srv/docker/kanboard/plugins:/var/www/app/plugins 
    kanboard/kanboard:latest
  • nginx
docker container run -d --name nginx 
    --restart always 
    -p 80:80 
    --network gogs-net 
    -v /var/run/docker.sock:/tmp/docker.sock:ro 
    jwilder/nginx-proxy:alpine

注:关键是容器通过 -e VIRTUAL_HOST 指定 url,通过 -e VIRTUAL_PORT=80 指定端口,同样端口也必须是原始镜像 expose 的端口。

延伸

目前服务都是通过 shell 启动,可改成通过 Docker Compose 统一编排任务,把 dnsmasq+nginx+gogs+… 等统一管理。如果是部署在公网上的话,还可以把 SSL 证书到期自动刷新等一起编排。

—EOF—

nginx安装lua/replace-filter-nginx-module

nginx加载lua和replace-filter-nginx-module模块

一、lua部分

首先下载和安装部分模块

1、下载安装LuaJIT

官网:http://luajit.org/
下载链接:http://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz

wget http://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz
tar zxvf LuaJIT-2.1.0-beta3.tar.gz
cd LuaJIT-2.1.0-beta3
make PREFIX=/usr/local/luajit-2.1 
make install PREFIX=/usr/local/luajit-2.1

设置好环境变量

export LUAJIT_LIB=/usr/local/luajit-2.1/lib
export LUAJIT_INC=/usr/local/luajit-2.1/include/luajit-2.1

2、下载ngx_devel_kit

wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1rc1.tar.gz
tar zxvf v0.3.1rc1.tar.gz

3、下载lua-nginx-module

wget https://github.com/openresty/lua-nginx-module/archive/v0.10.12rc2.tar.gz
tar zxvf v0.10.12rc2.tar.gz

4、下载安装sregex

wget https://github.com/openresty/sregex/archive/v0.0.1.tar.gz
cd sregex-0.0.1
make
make install

需要做软链

ln -s /usr/local/lib/libsregex.so.0.0.1 /usr/lib64/libsregex.so.0
ln -s /usr/local/lib/libsregex.so.0.0.1 /usr/lib/libsregex.so.0

否则报错:

/usr/local/nginx/sbin/nginx: error while loading shared libraries: libsregex.so.0: cannot open shared object file: No such file or directory

5、下载replace-filter-nginx-module

wget https://github.com/openresty/replace-filter-nginx-module/archive/v0.01rc5.tar.gz
tar zxvf v0.01rc5.tar.gz

6、安装nginx加载以上模块

./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module  --with-http_realip_module --add-module=../ngx_http_substitutions_filter_module-0.6.4/ --with-http_sub_module --add-module=../ngx_devel_kit-0.3.1rc1 --add-module=../lua-nginx-module-0.10.11 --with-ld-opt=-Wl,-rpath,/usr/local/luajit-2.1/lib --add-module=../replace-filter-nginx-module-0.01rc5/
make
make install

安装完毕

lvs,nginx,haproxy的优缺点,适合场景

Nginx/LVS/HAProxy的基于Linux的开源免费的负载均衡软件。

LVS:使用集群技术和Linux操作系统实现一个高性能、高可用的服务器,它具有很好的可伸缩性、可靠性和可管理性,是一款强大实用的开源软件。

LVS的优点:

1:抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,也保证了均衡器I/O的性能不会受到大流量的影响。;
2:lvs是专门的负载均衡软件,对任何应用都可以做负载均衡;
3:工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,目前用的比较多的是lvs+keepalived,比较大型的用的多的是lvs+heartbeat。

nginx的优点:

1:Nginx的高并发,同时能承载上万个并发连接;
2:nginx有充足的第三方功能模块的支持,主要通过upstream模块进行负载均衡;
3:nginx对网络的依赖较小,理论上只要Ping得通,网页访问正常,nginx就能连得通;
4:工作在网络的7层之上,可以针对http应用做一些分流的策略,它的正则规则比haproxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,nginx单凭这点可利用的场合就远多于lvs了。

nginx的缺点:

1:将Nginx当做反向代理时,负载均衡功能不是很好,对后端服务器的健康检查功能较弱;
2:nginx仅能支持http、https和email协议,这样就在适用范围上面小些,这个是它的缺点;
3:nginx只支持通过端口来检测,不支持通过url来检测。

haproxy的优点:

1:HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态;
2:haproxy也是专门的负载均衡软件,Haproxy可以负载http,还可以负载均衡mysql;
3:HAProxy是支持虚拟主机的。

总结这么多,我觉得根据不同的需求,不同的功能,可以选择不同的软件类的负载均衡软件,当然也是可以选择硬件类的负载均衡器。
像对于大型的,需要进行高并发的网站或者对网络不太严格的时候,可以使用nginx;
对于大型的Web服务器的时候可以使用haproxy;
对性能有严格要求的时候可以使用lvs,就单纯从负载均衡的角度来说,lvs也许会成为主流,更适合现在大型的互联网公司。

CentOS 7,使用yum安装Nginx

当使用以下命令安装Nginx时,发现无法安装成功

yum install -y nginx

需要做一点处理。

安装Nginx源

执行以下命令:

rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

安装该rpm后,我们就能在/etc/yum.repos.d/ 目录中看到一个名为nginx.repo 的文件。

安装Nginx

安装完Nginx源后,就可以正式安装Nginx了。

yum install -y nginx

Nginx默认目录

输入命令:

whereis nginx

即可看到类似于如下的内容:

nginx: /usr/sbin/nginx /usr/lib64/nginx /etc/nginx /usr/share/nginx

以下是Nginx的默认路径:

(1) Nginx配置路径:/etc/nginx/
(2) PID目录:/var/run/nginx.pid
(3) 错误日志:/var/log/nginx/error.log
(4) 访问日志:/var/log/nginx/access.log
(5) 默认站点目录:/usr/share/nginx/html

事实上,只需知道Nginx配置路径,其他路径均可在/etc/nginx/nginx.conf 以及/etc/nginx/conf.d/default.conf 中查询到。

常用命令

(1) 启动:

nginx

(2) 测试Nginx配置是否正确:

nginx -t

(3) 优雅重启:

nginx -s reload

(4) 查看nginx的进程号:

ps -ef |grep nginx

(5)nginx服务停止

nginx -s stop
kill -9 pid

当然,Nginx也可以编译源码安装,步骤相对要繁琐一些,总的来说,还是比较简单的,本文不作赘述

使用nginx或tomcat搭建https环境

前言

最近在做一个服务端和手机端相结合的项目,已接近尾声。

手机最初安装app是通过扫描二维码来下载安装的,这个方式在当下也较为流行。用此方法Android自然是没有问题,但是ios实现起来就没这么简单了。

因为是企业app使用的是企业证书不上appstore,所以只能使用safari来安装,步骤大致如下:

  • 安装证书,这里的证书必须安装,否则在连接下面的xxx.plist文件地址时会提示连不上服务器。

  • 访问xxx.plist文件,一般就是用户看到的安装按钮,地址就像这样:itms-services://?action=download-manifest&url=https://xxx.xxx/download/xxx.plist

  • 具体的安装操作是由xxx.plist文件中描述指定的,当然这步用户不会感觉到。xxx.plist文件ios开发人员会提供这里就不多说了。

我们要做的就是解决前面两步,本来是相当简单的事,但是苹果在ios7之后要求xxx.plist文件的地址必须是https的,这个就是麻烦的所在,因为我们原来没有https环境。

本来想着网上找个开放的https环境,把xxx.plist文件往上一放就解决了事,比如git.oschina.net实测就可以支持,但是领导要求这玩意不能放在别人那里,好吧,只能自己搭建一个了。

首先看了红薯的这篇: http://www.oschina.net/question/12_23148?fromerr=SUotMsG2

看来也挺简单的,按照说明搭建成功,浏览器也访问正常,可ios就是用不了。

后来折腾过才知道原来ios要求安装的证书是ssl的证书,并非ios开发者的证书,可上面的教程中并没有提供给ios安装的证书文件啊,看样子没这么简单搞定了,还是老老实实一步步来吧。

使用openssl生成证书

mac已经自带了openssl可以直接使用,如果没有请自行安装。

创建根证书

1、创建根证书私钥文件

openssl genrsa -out dexcoder.key 2048

2、创建根证书dexcoder.cer,机构名称为Dexcoder CA

openssl req -new -x509 -key dexcoder.key -out dexcoder.cer -days 3650 -subj /CN="Dexcoder CA"

创建自签名的ssl证书

1、创建一个私钥server.key

openssl genrsa -out server.key 2048

2、创建CSR,我这里是本地所以是:localhost,也可以改成IP,输出文件为server.csr

openssl req -new -out server.csr -key server.key -subj /CN=localhost

3、用CSR创建SSL证书,有效期为10年,输出文件为server.cer,序号文件为server.serial(撤销证书时使用)

openssl x509 -req -in server.csr -out server.cer -CAkey dexcoder.key  -CA dexcoder.cer -days 3650 -CAcreateserial -CAserial server.serial

配置nginx

到上面为止,证书就已经生成完成了,如果使用nginx,只需要进行如下配置:

server {
    listen       8443 ssl;
    server_name  localhost;
    ssl_certificate      /Users/liyd/testssl/server.cer;
    ssl_certificate_key  /Users/liyd/testssl/server.key;
}

重启nginx后就可以使用地址:https://localhost:8443 来访问了。

因为是自签名证书而非第三方认证机构签发,所以浏览器会出现以下提示:

未分类

但这并不影响我们ios应用的下载,就不管它了。

配置tomcat

上面nginx的配置已经完成了,但因为线上已经有一台tomcat,所以想着能不能并到一起,方便也节省资源。

tomcat要使用上面的证书,还需要做一下加工,因为tomcat使用的一般只有一个.keystore文件。

1、将.key 和.cer 文件导出为.p12 证书,需要输入证书密码。这里密码设为123456。输出文件名为server.p12。

selflydeMacBook-Pro:testssl liyd$ openssl pkcs12 -export -in server.cer -inkey server.key -out server.p12 -name "server"
Enter Export Password:
Verifying - Enter Export Password:
selflydeMacBook-Pro:testssl liyd$

2、用keytool将.p12文件导入到.keystore中,这里srcstorepass后面的123456为server.p12的密码,deststorepass后的12356为.keystore的密码。

selflydeMacBook-Pro:testssl liyd$ keytool -importkeystore -v -srckeystore server.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore server.keystore -deststoretype jks -deststorepass 123456
已成功导入别名 server 的条目。
已完成导入命令: 1 个条目成功导入, 0 个条目失败或取消
[正在存储server.keystore]
selflydeMacBook-Pro:testssl liyd$

3、使用ssl证书

打开Tomcat安装目录,修改conf目录下的server.xml,增加下面内容,原来注释部分应该有类似标签内容,可以参考:

<Connector SSLEnabled="true" protocol="org.apache.coyote.http11.Http11Protocol"  
            scheme="https" secure="true" sslProtocol="TLS"
            keystoreFile="/Users/liyd/testssl/server.keystore" keystorePass="123456"
            maxThreads="150" port="8443" clientAuth="false" 
            />

这里设置了端口为8443,启动tomcat,打开浏览器访问:https://localhost:8443/ 成功打开tomcat主页,说明服务已经可用。

ios安装证书

上面做了这么多,现在才是我们的最终目的,将dexcoder.cer放到部署的tomcat中,供ios访问下载,例如:

https://localhost:8443/app/dexcoder.cer

这个证书下载不一定要是https的,在安装好证书之后,再访问plist文件安装:

itms-services://?action=download-manifest&url=https://xxx.xxx/download/xxx.plist

这里的xxx.plist文件地址才必须是https。

结束语

到这里我们要的功能就都已经搞定了。不足之处是证书是自签名的,浏览器在访问时会出现安全警告。

如果想要去掉这个警告,可以申请第三方CA机构的证书,这个可以自己网上找找。

以下是摘自网上的一段关于CA机构及证书的说明:

要获取受浏览器信任的证书,则需要到证书提供商处申请。证书授证中心,又叫做CA机构,为每个使用公开密钥的用户发放一个数字证书。浏览器在默认情况下内置了一些CA机构的证书,使得这些机构颁发的证书受到信任。VeriSign即是一个著名的国外CA机构,工行、建行、招行、支付宝、财付通等网站均使用VeriSign的证书,而网易邮箱等非金融网站采用的是中国互联网信息中心CNNIC颁发的SSL证书。一般来说,一个证书的价格不菲,以VeriSign的证书为例,价格在每年8000元人民币左右。

据说也有免费的证书可以申请。和VeriSign一样,StartSSL也是一家CA机构,它的根证书很久之前就被一些具有开源背景的浏览器支持(Firefox浏览器、谷歌Chrome浏览器、苹果Safari浏览器等)。后来StartSSL竟然搞定了微软:在升级补丁中,微软更新了通过Windows根证书认证(Windows Root Certificate Program)的厂商清单,并首次将StartCom公司列入了该认证清单。现在,在Windows 7或安装了升级补丁的Windows Vista或Windows XP操作系统中,系统会完全信任由StartCom这类免费数字认证机构认证的数字证书,从而使StartSSL也得到了IE浏览器的支持。