导航

    YACLOUD
    • 注册
    • 登录
    • 搜索
    • 版块
    • 最新
    • 话题
    • 热门
    • 用户
    • 群组
    • 搜索
    1. 主页
    2. jiangytcn
    3. 帖子
    • 资料
    • 更多
      • 举报资料
      • 屏蔽用户
      • 关注
      • 粉丝
      • 主题
      • 帖子
      • 最佳
      • 群组

    jiangytcn 发布的帖子

    yet another oh-my-zsh theme with vault and hostname display

    Customized oh-my-zsh theme with ruby and vault address support

    create the following theme for .oh-my-zsh/custom/themes/ya.zsh-theme and then update ~/.zshrc file with

    ZSH_THEME="ya"

    #ya.zsh-theme
    # vim:ft=zsh ts=2 sw=2 sts=2
    
    rvm_current() {
      rvm current 2>/dev/null
    }
    
    rbenv_version() {
      rbenv version 2>/dev/null | awk '/[0-9]/{print $1}'
    }
    
    PROMPT='
    %{$fg_bold[green]%}${PWD/#$HOME/~} $(hostname)%{$reset_color%}$(git_prompt_info) ⌚ %{$fg_bold[red]%}%*%{$reset_color%}
    $ '
    
    # Must use Powerline font, for \uE0A0 to render.
    ZSH_THEME_GIT_PROMPT_PREFIX=" on %{$fg[magenta]%}\uE0A0 "
    ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
    ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[red]%}!"
    ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[green]%}?"
    ZSH_THEME_GIT_PROMPT_CLEAN=""
    
    if [ -e ~/.rvm/bin/rvm-prompt ]; then
      RPROMPT='%{$fg_bold[red]%}‹$(rvm_current)›%{$reset_color%} $VAULT_ADDR %{$fg_bold[blue]%}$HOME%{$reset_color%}'
    else
      if which rbenv &> /dev/null; then
        RPROMPT='%{$fg_bold[red]%}$(rbenv_version)%{$reset_color%} $VAULT_ADDR %{$fg_bold[blue]%} $HOME %{$reset_color%}'
      fi
    fi
    
    
    发布在 Blogs •
    A method to manage postgres database created in cloudfoundry

    Most of cloudfoundry based platform have postgres service in their catalog, applications could using the credentials bounded to their running environment for accessing, but sometimes the administrator need to access the database instance for whatever reason, debugging or checking specific record.

    TeamPostgreSQL is a project of Webworks (webworks.dk), which is excellent for the webui based database management, using a single browser, user could manage the postgresql database.

    1. download release
    /usr/bin/curl -# http://cdn.webworks.dk/download/teampostgresql_multiplatform.zip -o teampostgresql_multiplatform.zip && \
    unzip teampostgresql_multiplatform.zip && rm -f teampostgresql_multiplatform.zip
    
    1. generate deploy manifest file for teampostgresql

    The application would use java buildpack for compiling and hosting, and need to specify JBP_CONFIG_JAVA_MAIN otherwise the http service won't start correctly

    ---
    applications:
    - name: psqlgui
      memory: 1G
      buildpack: https://github.com/cloudfoundry/java-buildpack.git
      host: psqlgui
      env:
        JBP_CONFIG_JAVA_MAIN: '{arguments: "-cp WEB-INF/lib/log4j-1.2.17.jar-1.0.jar:WEB-INF/classes:WEB-INF/lib/* dbexplorer.TeamPostgreSQL $PORT"}'
    
    
    1. Deploy

    using the following script to deploy application, before executing, need to obtain an account of cloudfoundry

    #!/bin/bash
    
    
    WORK_DIR=`dirname "${0}"`
    RUN_DIR=$TMPDIR
    
    cf --version > /dev/null
    
    if [[ $? -gt 0 ]];
        then
        echo "CloudFoundry cli not installed"
        exit 1
    fi
    
    cf push -f $WORK_DIR/manifest.yml -p $RUN_DIR/teampostgresql/webapp
    

    After the deployment, the application could be access through webui and then configure database with credential of postgresql database instance

    发布在 Blogs •
    How to host your own Silex on CloudFoundry based PaaS

    why

    Silex, is a free and open source website builder in the cloud. Create websites directly in the browser without writing code. And it is suitable for professional designers to produce great websites without constraints. Silex is also known as the HTML5 editor. And we want to leverage the Cloud Foundry to host our own site of Silex, so you are here ! 😉

    Prerequisite

    You need to have an Cloud Foundry account, whatever Bluemix or PCF, both are the instance of Cloud Foundry Stack. For detail about them , pls referral to the link below and what you need to know is the follwing commands

    • cf login
    • cf push
    • cf set env
    • cf start
    • (Optional) Activate github service you need to define the env vars GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET (Create a github app here)

    Host an instance of Silex in Cloud Foundry

    1. Clone this repository, and do not forget the sub modules (cloud-explorer and unifile)
    $ git clone --recursive -b cf-integration https://github.com/silexlabs/Silex.git
    
    1. Go to Silex's Directory.
    $ cd yadesigner
    
    1. Login to the Bluemix
    $ cf login -a api.ng.bluemix.net -u <you username here>
    and input the password in the interactive Shell
    
    $ cf push -m 2G <your add name here> p -b https://github.com/dgodd/jdk-buildpack -b nodejs_buildpack --no-start
    $ wait...
    $ ...
    $ cf set-env <your add name here> GITHUB_CLIENT_ID <GITHUB_CLIENT_ID value here>
    $ cf set-env <your add name here> GITHUB_CLIENT_SECRET <GITHUB_CLIENT_SECRET value here>
    
    $ cf start <your add name here>
    

    After deploy you could vist your own silex site

    Recap

    The reason why use multiple buildpacks for the application is Silex using Google Closure Complier to build js, which depends on JDK for the application staging phase. The Java buildpack above is not community official supported, casue community still not decided what's the best way to support of the use case like this in general solution.

    Links

    • Bluemix official website
    发布在 Blogs •
    Kubernetes Easy Way -- consul and vault

    本文主要介绍如果通过Terraform 和Vault 轻松构建Kubernetes 集群环境

    OS CPU MEM DISK
    Ubuntu 18.04.1 LTS Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz 32G 2T Extra Disk

    Containerized Vault 和 Consul 安装

    $ mkdir -p /hdd/k8s-easy-way/{consul_data,vault_data,vault_config}

    #192.168.1.10 替换为安装机器的地址

    docker run -d --name consul-server -v "/hdd/k8s-easy-way/consul_data":/consul/data --net=host -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' consul agent -server -bind=192.168.1.10 -retry-join=192.168.1.10 -bootstrap-expect=1 -ui -client=192.168.1.10

    #创建vault配置文件

    $ cat vault_config/config.hcl

    storage "consul" {
    address = "192.168.1.10:8500"
    path = "vault"
    }

    listener "tcp" {
    address = "0.0.0.0:8200"
    tls_disable = 1
    }

    $docker run -d --name vault-server -p 8200:8200 --cap-add=IPC_LOCK -v $(pwd)/vault_data:/vault/logs -v $(pwd)/vault_config:/vault/config -e 'VAULT_LOCAL_CONFIG={"default_lease_ttl": "168h", "max_lease_ttl": "720h"}' vault server

    • https://www.vaultproject.io/downloads.html, 选择与实验环境对应的平台的vault cli

    $export VAULT_ADDR=http://192.168.1.10:8200

    #初始化vault环境
    $vault operator init

    #查询vault application的log
    $docker logs vault-server -f
    ...
    ...
    authenticated to the CLI, so you can immediately begin using Vault.

    You may need to set the following environment variable:

    $ export VAULT_ADDR='http://127.0.0.1:8200'
    

    The unseal key and root token are displayed below in case you want to
    seal/unseal the Vault or re-authenticate.

    Unseal Key: yzDDBRsxjw2E4yjT2hCJVoLom2hSMiCSp1wxWBv4pso=
    Unseal Key: yzDDBRsxjw2E4yjdaCJVoLom2hSMiCSp1wxWBv4pso=
    Unseal Key: ysfw2E4yjT2hCJVoLom2hSMiCSp1wxWBv4pso=
    Unseal Key: yzDDBRsxjw2E4yjd2VoLom2hSMiCSp1wxWBv4pso=
    Unseal Key: yzDs3T2hCJVoLom2hSMiCSp1wxWBv4pso=
    Root Token: a95bb2c6-2641-d0be-820e-3ad27c06f800

    ==> Vault server started! Log data will stream in below:

    ...
    ...

    初始情况下,vault处于sealed 状态,需要通过上面获取到的5个unseal key来对vault server进行unseal
    重复执行三次下面这条命令,根据提示输入不同的unseal key
    $vault operator unseal
    ...
    $ vault operator unseal
    Key Value


    Seal Type shamir
    Sealed false
    Total Shares 5
    Threshold 3
    Version 0.11.1
    Cluster Name vault-cluster-eced0aa0
    Cluster ID a5fe7988-04e2-d339-c072-653e4d962e4e
    HA Enabled true
    HA Cluster n/a
    HA Mode standby
    Active Node Address <none>

    执行最后一次操作后,可以看到sealed状态是false,此时登录vault, 根据提示输入root token

    $ vault login
    Success! You are now authenticated. The token information displayed below
    is already stored in the token helper. You do NOT need to run "vault login"
    again. Future Vault requests will automatically use this token.

    Key Value


    token c82805e8-580d-9652-6683-83dd900cdcd7
    token_accessor 4ef08e65-8e22-8598-b756-971dd7404034
    token_duration ∞
    token_renewable false
    token_policies ["root"]
    identity_policies []
    policies ["root"]

    启用kv version2 功能

    $vault secrets enable kv -version=2
    Success! Enabled the kv secrets engine at: kv/

    version 2 的kv secret 功能特殊之处在于,每次对secret 的路径进行的修改,在vault 系统中对会有对应的版本信息,类似于git的提交,都可以进行找回. 平台的管理员可以对保存的副本进行配置

    $ vault kv put /kv/foo val=bar
    Key Value


    created_time 2018-09-13T13:59:23.162374714Z
    deletion_time n/a
    destroyed false
    version 1

    $ vault kv put /kv/foo val=bar-v2
    Key Value


    created_time 2018-09-13T13:59:31.499522355Z
    deletion_time n/a
    destroyed false
    version 2

    $ vault kv get /kv/foo
    ====== Metadata ======
    Key Value


    created_time 2018-09-13T13:59:31.499522355Z
    deletion_time n/a
    destroyed false
    version 2

    === Data ===
    Key Value


    val bar-v2

    目前为止,已经配置好了可持久化的已consul作为数据存储节点的vault 服务,在下一章节,将讲述如何为kubernetes control plane 各服务节点配置证书

    发布在 Blogs •
    解决Mac上VirtualBox 虚拟机网络无法连通问题

    最近在使用Mac上的VirtualBox 创建出的虚拟机做K8S相关的开发工作, 物理机有时重启后无法连接到虚拟机当中,ICMP拒绝, 但是在VM 内部以及VM间网络通信都是正常的。重启Mac后问题可以解决,但是不是解决问题之道,经过排查,发现Mac上的到虚拟机hostonly 网络的路由丢失,导致连接失败

    查看当前物理机上的hostonly 网卡信息

    $ VBoxManage list hostonlyifs
    Name: vboxnet0
    GUID: 786f6276-656e-4074-8000-0a0027000000
    DHCP: Disabled
    IPAddress: 192.168.50.1
    NetworkMask: 255.255.255.0
    IPV6Address:
    IPV6NetworkMaskPrefixLength: 0
    HardwareAddress: 0a:00:27:00:00:00
    MediumType: Ethernet
    Wireless: No
    Status: Up
    VBoxNetworkName: HostInterfaceNetworking-vboxnet0

    Name: vboxnet1
    GUID: 786f6276-656e-4174-8000-0a0027000001
    DHCP: Disabled
    IPAddress: 192.168.59.1
    NetworkMask: 255.255.255.0
    IPV6Address:
    IPV6NetworkMaskPrefixLength: 0
    HardwareAddress: 0a:00:27:00:00:01
    MediumType: Ethernet
    Wireless: No
    Status: Down
    VBoxNetworkName: HostInterfaceNetworking-vboxnet1

    Name: vboxnet2
    GUID: 786f6276-656e-4274-8000-0a0027000002
    DHCP: Disabled
    IPAddress: 192.168.99.1
    NetworkMask: 255.255.255.0
    IPV6Address:
    IPV6NetworkMaskPrefixLength: 0
    HardwareAddress: 0a:00:27:00:00:02
    MediumType: Ethernet
    Wireless: No
    Status: Down
    VBoxNetworkName: HostInterfaceNetworking-vboxnet2

    添加dhcp server

    VBoxManage dhcpserver modify --ifname vboxnet0 --ip 192.168.50.2 --netmask 255.255.255.0 --lowerip 192.168.50.100 --upperip 192.168.50.199 --enable

    查看虚拟机网络网关的路由信息

    $ route get 192.168.50.1
    route to: 192.168.50.1
    destination: default
    mask: default
    gateway: 192.168.1.1
    interface: en0
    flags: <UP,GATEWAY,DONE,STATIC,PRCLONING>
    recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
    0 0 0 0 0 0 1500 0
    可以看到此网络的网关走到了192.168.1.1 此地址为Mac机器的网关,所以到该虚拟网络的流量都会通过gw 出去,因此也就到达不了虚拟机内部

    添加到虚拟网络地址段的路由

    $ sudo route -nv add -net 192.168.50 -interface vboxnet0 2.2.2 /Users/jiangytcn

    u: inet 192.168.50.0; u: link vboxnet0:a.0.27.0.0.0; u: inet 255.255.255.0; RTM_ADD: Add Route: len 140, pid: 0, seq 1, errno 0, flags:<UP,STATIC>
    locks: inits:
    sockaddrs: <DST,GATEWAY,NETMASK>
    192.168.50.0 vboxnet0:a.0.27.0.0.0 255.255.255.0
    add net 192.168.50: gateway vboxnet0

    $ route get 192.168.50.114
    route to: 192.168.50.114
    destination: 192.168.50.0
    mask: 255.255.255.0
    interface: vboxnet0
    flags: <UP,DONE,CLONING,STATIC,PRCLONING>
    recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
    0 0 0 0 0 0 1500 -438
    此时可以看到,到该虚拟网络的地址都通过vboxnet0

    $ ping 192.168.50.115
    PING 192.168.50.115 (192.168.50.115): 56 data bytes
    64 bytes from 192.168.50.115: icmp_seq=0 ttl=64 time=0.287 ms
    ^C
    --- 192.168.50.115 ping statistics ---
    1 packets transmitted, 1 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 0.287/0.287/0.287/0.000 ms

    发布在 Blogs •
    CloudStack: 线上系统设置debug模式以及子工程编译

    此文原写于 12 February 2014, 当时刚做CloudStack 相关开发不久,由于项目需要,需要线上对环境进行调试。CloudStack 本身是Java 编写,可以运行于tomcat 容器当中, 通过对tomcat的配置,可以进行调试

    编辑Tomcat
    根据tomcat安装的具体情况,进行修改。默认是/usr/sbin/tomcat6
    添加参数 -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8787 到此启动文件当中,大致添加后如下

    35 -Djava.io.tmpdir="$CATALINA_TMPDIR"
    36 -Djava.util.logging.config.file="${CATALINA_BASE}/conf/logging.properties"
    37 -Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager"
    38 -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8787 \

    重启tomcat 容器,之后按照一般的eclipse debug 模式连接进行调试

    编译单独的子工程

    在项目开发过程当中,对某一个组件进行修改是再正常不过的了,CloudStack 是以maven 进行工程组装打包发布的,以cloud-server为例,如果我们想对修改后的工程,使其能够生效,可以单独编译该工程后,将编译发布后的jar文件替换原有的文件,重启管理节点后即可生效
    cd ~/cloudstack4.1.0 mvn clean mvn -pl :cloud-server
    在终端可以看到编译过程,最后可以看到如下信息

    Total time: 3:01.915s
    Finished at: Wed Feb 12 14:56:24 CST 2014
    Final Memory: 26M/233M

    将新编译后的jar 文件替换原有的 cloud-server-4.1.0.jar, 重启管理节点。


    版本信息

    软件 版本
    CloudStack 4.1.0
    tomcat 6
    发布在 Blogs •
    CloudStack: VM Failes to start with error: VDI not available

    在使用cloudstack的过程中可能会遇到如下的问题, ssh登录到虚拟机内部,执行关机命令(shutdown -h now), 在NFS backend下的Vm出现通过CloudStack无法启动的问题

    产生原因
    Xenserver 与存储设备或者Lun失去连接

    解决方法
    从CloudStack的管理节点中查找出该虚拟机的VDI 设备的编号(UUID)
    日志文件地址默认是 /var/log/cloud/management/management-server.log, 可能的VDI UUID 值为 6f97582c-xxxx-xxxx-xxxx-9aa5686bcbd36. 并会伴有类似 VM are failing to start with “errorInfo: [SR_BACKEND_FAILURE_46, The VDI is not available 这样的日志记录。

    登录到Xenserver 中, 执行以下命令

    查找出该UUID 对应的vid 设备的的信息, 包含sr-uuid 以及name-label 信息
    xe vdi-list uuid=<日志文件中查找出的VDI uuid> params=sr-uuid, name-label
    xe vdi-forget uuid=<日志文件中查找出的VDI uuid>
    xe sr-scan uuid=<SR uuid>
    xe vdi-param-set uuid=< 日志文件中查找出的VDI uuid> name-label=< 之前查找出的name-label >

    重启cloudstack 管理节点来使数据同步


    版本信息

    软件 版本
    CloudStack 4.2.1
    Xenserver 6.2.0
    发布在 Blogs •
    Windows 2016 server 单机版配置ldaps 以及ubuntu 客户端ssl 连接配置

    Windows 2016 server上配置Active Directory 以及Domain Controller,CA 并启用ldaps认证功能

    1. Windows 2016 安装
      通过微软官网下载iso 镜像进行安装,下载后有180的试用期。注意安装时选择带有桌面功能的数据中心版本。
      具体过程省略, 可自行搜索

    2. AD 安装配置
      系统启动后进行ad的安装配置,安装配置过程没有特殊之处。

    3. CA 安装以及配置
      具体过程省略。

    4. 证书导出
      需要注意的是,到处的是AD server的证书

    5. Ubuntu 客户端配置

      1. 安装OpenSSL 以及Ca 管理工具
        apt update && apt install openssl ca-certifcates ldap-utils

      2. 更新CA database
        mkdir /usr/share/ca-certificates/devbox/
        将导出的server的证书上传至上述创建的目录中
        编辑ca配置,加载新的证书

        root@a9ad14a3288f:/# tail -n 2 /etc/ca-certificates.conf
        mozilla/thawte_Primary_Root_CA_-_G3.crt
        devbox/server_certificate.cer

        root@a9ad14a3288f:/# update-ca-certificates
        Updating certificates in /etc/ssl/certs...
        1 added, 0 removed; done.
        Running hooks in /etc/ca-certificates/update.d...
        done.

        验证证书配置

        openssl s_client -connect WIN-2PHSJD5NH12.ad.devbox.int:636 -showcerts

        通过ldaps 连接AD server

        root@a9ad14a3288f:/# ldapsearch -x -H ldaps://WIN-2PHSJD5NH12.ad.devbox.int -D 'administrator@ad.devbox.int' -w 'Passw0rd' -b "DC=ad,dc=devbox,dc=int" "(objectclass=user)" dn

    发布在 Blogs •
    K8S Ingress Controller 之 traefiker

    关于K8S的Ingress Controller, 顾名思义,是负责处理Ingress请求的模块。如果熟悉CloudFoundry的话,可以把它想像成Gorouter的功能,由于在PaaS/CaaS中,每一个业务后端实际是由多个容器来支撑,如何将用户的请求按照一定的算法,round-robin 抑或是least-connection,分配到不同的容器当中,这个是Ingress Controller的作用。
    关于K8S当中的Ingress 的定义,可以参考 官方文档

    Traefik 其功能是HTTP层的方向代理以及负载均衡器,可以在其它的容器调度平台,如K8S、Mesos、Docker上部署微服务。本文主要介绍如何通过 traefik 在Minikube上配合 nip.io 为微服务提供访问服务。


    前置条件

    【1】 kubernetes 环境 本文以minikube 为例
    【2】kubectl 客户端安装
    【3】internet 访问权限

    安装 traefik

    在其官方文档中,提供了安装步骤,抽取了关键步骤,想要看详细介绍的,移步 ->

    RBAC 配置

    如果k8s cluster启用了RBAC之后,需要对Traefik 授权 ClusterRole 以及ClusterRoleBinding 来使用Kubernets 的API

    kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml

    安装Traefik

    关于DeploymentSet 以及 Deployment有以下的区别

    1. 相比较DaemonSet 而言,Deployment 有更好的扩展性,如果使用了DS,那么在每一个node上只有一个pod

    2. 通过taints tolerations, DS可以在专有的机器上运行Service.可以参考

    3. 除此之外, DS可以直接访问任意Node上面的80, 443 端口,但是如果使用Deployment的话,那么需要设置一个Service 对象.

    通过DaemonSet 安装

    kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-ds.yaml

    配置Ingress 并启用UI

    Traefik 提供了webui供查看其上的配置信息

    kubectl apply -f https://raw.githubusercontent.com/yacloud-io/k8s-hands-on/master/ingress-controller/traefik-ui.yml

    通过浏览器访问 http://traefik-ui.192.168.99.100.nip.io/dashboard/#/

    Treafik UI with nip.io

    安装terrific 并为其配置ingress

    terrific web server,访问后,会显示所运行的容器/宿主机的IP 地址信息

    安装terrific deployment

    kubectl apply -f https://raw.githubusercontent.com/yacloud-io/k8s-hands-on/master/ingress-controller/terrific-deployment.yml

    为其配置Service
    kubectl apply -f https://raw.githubusercontent.com/yacloud-io/k8s-hands-on/master/ingress-controller/terrific-service.yml

    配置Ingress 规则
    kubectl apply -f https://raw.githubusercontent.com/yacloud-io/k8s-hands-on/master/ingress-controller/nip.io-ingress.yml

    在deployment的pod 启动后,访问 http://my-terrific.192.168.99.100.nip.io/ 查看结果

    terrific ingress
    刷新浏览器,可以看到访问到不同的容器上

    总结

    traefik作为K8S的负载均衡器,为其上部署的应用提供外部访问的能力。默认情况下,K8S提供了NodePort、LoadBalancer 的方式来访问,但是在IP资源有限的情况下,特别是以NodePort报露外部请求时,Worker 节点有时不是公网IP,用Traefik可以很方便的解决这个问题,并提供负载均衡。

    发布在 Blogs •
    云磁盘加密之 LUKS

    任何在云上部署的应用都离不开持久化盘或者说是数据盘,在的虚拟机的使用场景里面,云服务提供商都会提供这样的一个服务。很多人可能不会理解为什么我创建的虚拟机不可以直接在上面写数据,而需要单独的去创建额外的磁盘进行数据的读写。

    以OpenStack为例,其虚拟机的配置由Flavor 来觉得,让我们来看下创建flavor 的属性是什么
    OpenStack Flavor Details

    可以看到其中定义了该VM的vCPU、内存以及root磁盘大小可以理解为sda。另外有一项比较特殊的是 ephemeral, 如果定义了该值后,在操作系统当中会额外的有一个存储设备sdb. 但是如果虚拟机所在的物理机或者由于删除该虚拟机的话,那么其上所写入的数据也会随之删除。所以有了个数据盘(Persistent Disk)的产生,该存储设备可以通过挂载的方式添加到虚拟机里面,OpenStack 里面有Cinder提供这样的服务,对于其它的云服务提供商来说,会有不同的服务。但是无论是那种,无论以什么协议添加到了虚拟机当中,其上面的数据如果不是人为的删除的话,可以放心使用。

    虽然persistent disk 解决了数据存储持久化的问题,但是也随之带来了另外的问题。
    其上存储的数据如何保护? 如果后端的存储服务器被黑客攻陷的话,那么其上的所有客户数据都会收到威胁, 如何防护云存储(对象 & 块存储)的安全变得直观重要。

    下面提供一种简单的但是有效的方式进行数据盘加密,即使是云服务提供商也无法任意的查看你的数据。


    Linux Unified Key Setup-on-disk-format (or LUKS) allows you to encrypt partitions on your Linux computer. This is particularly important when it comes to mobile computers and removable media. LUKS allows multiple user keys to decrypt a master key, which is used for the bulk encryption of the partition.

    该方法主要通过Linux 提供的LUKS进行磁盘的加密, 其全称为 Linux Unified Key Setup-on-disk-format (or LUKS). 对于移动设备或者可插拔的设备来说尤其的重要。LUKS允许多个用户用其Key 去解密 Master的Key。
    关于更多的介绍,请自行 Google Luks

    实验步骤

    ubuntu@ubuntu-xenial:~$ sudo shred -v --iterations=1 /dev/sdc
    sudo: unable to resolve host ubuntu-xenial
    shred: /dev/sdc: pass 1/1 (random)...

    ubuntu@ubuntu-xenial:~$ sudo cryptsetup --verbose --verify-passphrase >luksFormat /dev/sdc
    sudo: unable to resolve host ubuntu-xenial

    WARNING!
    = =======
    This will overwrite data on /dev/sdc irrevocably.

    Are you sure? (Type uppercase yes): YES
    Enter passphrase:
    Verify passphrase:
    Command successful.

    需要注意的是在确认时需要大写的 YES

    ubuntu@ubuntu-xenial:~$ sudo cryptsetup luksOpen /dev/sdc encrypted
    sudo: unable to resolve host ubuntu-xenial
    Enter passphrase for /dev/sdc:

    任何要操作该设备的操作都要之前输入的秘钥

    ubuntu@ubuntu-xenial:~$ ls -l /dev/mapper/ | grep encrypted
    lrwxrwxrwx 1 root root 7 Sep 21 04:27 encrypted -> ../dm-0

    ubuntu@ubuntu-xenial:~$ sudo mkfs.ext4 /dev/mapper/encrypted
    sudo: unable to resolve host ubuntu-xenial
    mke2fs 1.42.13 (17-May-2015)
    Creating filesystem with 261632 4k blocks and 65408 inodes
    Filesystem UUID: b84e4ca5-44f7-453a-a14b-0f0115c9913e
    Superblock backups stored on blocks:
    32768, 98304, 163840, 229376

    Allocating group tables: done
    Writing inode tables: done
    Creating journal (4096 blocks): done
    Writing superblocks and filesystem accounting information: done

    磁盘挂载

    ubuntu@ubuntu-xenial:~$ sudo mount /dev/mapper/encrypted /mnt/
    sudo: unable to resolve host ubuntu-xenial
    ubuntu@ubuntu-xenial:~$ df -h | grep mnt
    /dev/mapper/encrypted 990M 1.3M 922M 1% /mnt


    附

    通过👇的vagrant file 创建有附加磁盘的虚拟机供实验

     file_to_disk = 'encrypted-disk.vdi'
     
    Vagrant.configure("2") do |config|
      config.vm.box = "ubuntu/xenial64"
      config.vm.provider "virtualbox" do |vb|
        vb.gui = false
        vb.memory = "1024"
        vb.name = "luks"
      
        if !File.exist?(file_to_disk)
           vb.customize ['createhd', '--filename', file_to_disk, '--size',  1024]
        end
        vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, >'--type', 'hdd', '--medium', file_to_disk]
      end
    
      config.vm.provision "shell", inline: <<-SHELL
           apt-get update
           apt-get install -y ubuntu-desktop
      SHELL
     end
    

    参考

    Redhat Docs

    发布在 Security •
    User Namespaces 加固Docker container 宿主机

    Docker 容器以及其所运行的宿主机的安全防护是维护可信的服务的关键。 以专业的安全领域的DevOps角度来看, 对container 以及container 的调度平台想OpenShift、Docker Swarm以及如日中天的K8S进行安全防护其实很简单。 主要是因为在技术革新如此快速的时代,目标变化的也如此频繁。

    由于新技术的发展,其产生的许多挑战需要去解决,在解决这些问题的方法当中,有一项是有着重大意义,即在docker container当中对其宿主机的 UID和GID 映射到不同的值。

    有一些没有威胁性的配置的变更,通过一个不是那么新的技术User Namespaces 可以将在Container当中root user 与Host的root user进行隔离。这一特性在2016年2月前后发布的Docker 1.10 版本中已经可以使用。之所以称其为“不是那么新的技术” 是因为任何一个从事容器化以及调度层系统开发的人知道,一个功能如果发布了6个月以上就会被认为是一个”古董“ ;)

    实现细节

    以下会通过一些实验来验证 host 级别,确切来说是内核级别的 User Namespace 安全防护方法

    首先, 在谈到对Docker 容器或者其它平台的容器进行安全防防护时,有2个常见的相关联的术语。
    也许你会想到的是Cgroup,cgroup 可以将进程在内核当中进行限定。我所说的限定指的是限制其能占有系统资源的能力,包括CPU,RAM 以及 IO

    通过namespace 来控制一个进程其对系统资源的可视度并不会令你产生疑惑 。也许你并不想令某一个进程可以访问所有的网络协议栈或者其它在进程表当中的进程

    在接下来的实验当中,会选取Docker 作为容器的运行时环境。本文会对user和group在host当中的container进行重新的映射。host指的时运行docker 后台守护进程的服务器。
    更进一步,实验会通过改变容器进程对其资源的可视度来防护Host。

    对user和group的重映射即对user namespace 的操作来改变用户对系统当中其它进程的可视度。如果想更深入的了解其内部机制,没有什么比用户手册更适合不过的了。
    “User Namespace 对安全相关的标示、属性进行隔离,特别是User Id 和Group ID...”。
    “在一个user namespace当中的进程所属的User以及Group可以与其有所不同。特别是,进程在user namespace外可以有普通的非特权user 同时在user 命名空间中有特权用户0,也就是在内部可以有所有的操作权限,但是在外部只能进行非特权相关的操作”。

    下表提供了我们通过user namespace 想要实现的隔离

    username space 说明

    图片来源 https://endocode.com/blog/2016/01/22/linux-containers-and-user-namespaces/

    再来说明下我们想要达成的目标, 将host 上的超级用户(其user id 是 UID = 0)与容器当中的root 用户进行隔离。

    通过以上变更后,我们会得到神奇的效果,即使容器当中的应用 以root 用户去运行 并且其UID 是0,但是在现实当中并不会与host的超级用户有任何关联,也不会对系统造成影响。

    你可能会觉得这无足轻重。但是,可以想象以下这样的场景,如果容器的的权限被贡献了,因为使用了这一技术,攻击者无法在跳出了容器后进行权限的升级以控制宿主机上的其它服务, 也就无法控制宿主机。


    对docker 守护进程进行修改

    首要的条件是启用Docker 守护进程的 userns-remap

    值得指出的是,在现阶段你需要使用K8S V1.5 以上的版本以免由于使用了user namespaces 会对network namespace 进行破坏。从我观察到的是,K8S本身并不会产生问题,但是这是Network Namespace 的问题。

    另外,由于docker 版本的变化,对docker daemon添加参数有可能有所变化。如果你所使用的版本滞后1个月以上的化,那么十分的不幸。对于持续的更新是有代价的;向后兼容性或者说会耗费大量的精力。对于我来说,这并不是问题毕竟技术很fantastic。

    开始实验

    第一步是使docker 守护进程通过json 配置文件来启动, 而不是通过unix 类型的配置。
    添加 DOCKER_OPTS 到文件 /etc/default/docker 中。通过这种方式比通过修改 systemd 的unit 文件会简单的多。

    在所提到的文件当中,添加下面的配置,

    DOCKER_OPTS="--config-file=/etc/docker/daemon.json"

    没错 /etc/docker/daemon.json 文件中包含是json类型的配置文件,简单起见,省略了其它的配置信息,添加了--userns-remap 选项

    {

    "userns-remap": "default"

    }

    对于老得版本或者说是不同的linux 发新版 或者是个人的偏好,也可以直接添加这个参数DOCKER_OPTS="--user-remap=default"至文件/etc/default/docker 当中而不使用json 配置文件

    通过以下方式启动docker 守护进程

    $ dockerd --userns-remap=default

    希望通过以上的步骤对你来说是生效, 如果以上的配置对你来说不起作用还是Google吧


    到这一阶段,会注意到在上面的例子当中为了方便起见default 作为重新映射的用户。稍后我们会接着讨论。现在,你可以跳转到其它必须的配置参数来启用user namespace。

    如果你坚持像我上面所用的default 作为参数的化, 你应该添加以下的配置到下面的文件当中。对于Reahat 相关的发行版, 在重启按以上的配置后的docker daemon以前修改下列文件。对于其它的发行版,此文件有可能不存在,通过 echo 或者其它的命令创建此文件。

    echo "dockremap:123000:65536" >> /etc/subuid

    echo "dockremap:123000:65536" >> /etc/subgid

    按照不同的发行版执行相关的命令 重启docker daemon,如

    $ systemctl restart docker

    • 注意: 此种启动方式只适用于修改了daemon.json文件

    核心内容

    通过在上面的文件当中添加subordinate dockerremap user 和group 配置, 意思是说需要将容器的user ID和Group ID映射到宿主机的从123000到65536当中的一个值。理论上来说可以用65536 作为以上的起始值,但是实际来看这有所不同。在目前的版本当中, Docker 仅对第一个,UID进行映射。Docker 官方生成会在以后的版本中进行改进。

    上面说过会对所使用的default 的配置进行说明。这个值是是docker 内部可以像我们所看到的那样使用用户名和组名dockerremap。可以使用任意的名,但是要在重启docker daemon 之前对文件 /etc/subuid 和 /etc/subgid进行正确的修改。

    其它的更改

    注意,需要重新的拉取docker 镜像文件 之后会在宿主机的新的子目录进行更新。

    如果查看 /var/lib/docker 目录后,你会发现镜像存储目录由我们所熟悉的UID.GID 数字格式命名。

    $ ls /var/lib/docker

    drwx------. 9 dockremap dockremap 4096 Nov 11 11:11 123000.123000/

    从现在开始,如果像以下方式这样进入容器内部,你会发现所运行的应用程序是以root 和UID 为0 的方式运行。
    运行容器

    ubuntu@ubuntu-xenial:~$ sudo docker run --rm -d redis
    sudo: unable to resolve host ubuntu-xenial
    Unable to find image 'redis:latest' locally
    latest: Pulling from library/redis
    065132d9f705: Downloading 5.291MB/30.11MB
    be9835c27852: Download complete
    065132d9f705: Downloading 17.43MB/30.11MB
    ea1f878b621a: Downloading 5.799MB/8.268MB
    065132d9f705: Pull complete
    be9835c27852: Pull complete
    f4a0d1212c38: Pull complete
    ea1f878b621a: Pull complete
    7a838393b4b9: Pull complete
    9f48e489da12: Pull complete
    Digest: sha256:8a54dcc711406447b3631a81ef929f500e6836b43e7d61005fa27057882159da
    Status: Downloaded newer image for redis:latest
    4eb610618d04254245bbe29f3523641f2c4c1c9731e4c139f9e68a7e1c47de16

    $ docker exec -it 4eb610618d04 bash

    在物理机上,可以通过ps 命令来查看尽管该容器是以UID 为的0的用户来运行,但是实际上在物理机上,其值是UID=123000。

    $ ps -ef | grep redis

    如果系统支持的话,可以通过在宿主机和容器当中运行以下命令来获得相应的UID相关信息。

    $ ps -eo uid,gid,args

    限制条件

    和所有非原生的安全方案一样,也有一些取舍,然而对于User namespace来说不那么的繁重。

    注意,通过以上的配置后,在启动容器时就无法使用--net=host 或者使用--pid=host来共享 PID 。而且,你不能使用--read-only 的容器,因为对于一个使用了User Namespace的无状态的容器来说没有什么作用。

    此外,--privileged 模式的参数也无法使用,并且需要确保任何所挂载的文件系统,如NFS,允许UIDs和 GIDs访问

    对于像RedHat及其衍生的发行版,如Centos, 需要在boot loader中开启kernel的配置来启用User Namespace,通过grubby 命令进行配置:

    $ grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"

    重启机器后使参数生效。

    通过以下配置禁用该模式:

    $ grubby --remove-args="user_namespace.enable=1"
    --update-kernel="$(grubby --default-kernel)";

    结束语

    希望以上简单的配置能够对Docker 主机的安全防护有所帮助。

    最后一点, 任何人都不想获取了超级用户访问权限攻击者潜伏在主机当中,经过数月的学习研究配置的漏洞,即APT(Advanced Persistent Threat)的情况发生. 当然,任何人都不想要这一结果, 但是这却在你毫不知情的情况下实实在在的发生。仅仅是因为你从Docker hub中拉取了一个没有更新有漏洞包的镜像。保持警惕!

    On that ever so cheery note: Stay vigilant!


    实验playback

    环境信息

    ubuntu@ubuntu-xenial:~$ uname -r
    4.4.0-96-generic
    ubuntu@ubuntu-xenial:~$ cat /etc/issue.net
    Ubuntu 16.04.3 LTS

    ubuntu@ubuntu-xenial:~$ docker --version
    Docker version 17.06.2-ce, build cec0b72

    参考

    Introduction to User Namespaces in Docker Engine
    Control and configure Docker with systemd
    Its all about linux

    发布在 Security •
    CloudFoundry + OpenStack: Your Own Platform - Preview

    Building you own robust cloud platform with CloudFoundry and OpenStack

    PaaS 概念近年来在国内是越来越火了,随着OpenStack 的日渐成熟,无论是在企业级抑或是创业公司来说其普及率越来越高,似乎再考虑搭建云平台时不将OpenStack 考虑在那觉得有些out的感觉。Mesos on top of OpenStack、 K8S on top of OpenStack, 以及自研的产品 on top of OpenStack,... 似乎OpenStack 这一开源领域的os 的说法越来越多的被这些案例所证实。但真的是这样么?在其它的分享中会再谈下我自己的看法。
    此博客(可以说是一系列)初衷是将我近年来在OpenStack 以及CloudFoundry 所做的事做个总结,也为那些在PaaS产品选型以及在PaaS 这条路上刚入门的同学一些指导,如何通过这2个开源产品构建一个Out of Box 的Platform以及解决在使用过程中遇到的一些坑

    • 平台初见 --- Hello, World

    平台初见 --- Hello, World

    'Hello, World' -- 对于每一个干IT的人来说并不陌生,让我们看下在PaaS里面的HelloWorld 是什么样的。

    1. 如果你是刚刚接触PaaS的童鞋, 对PaaS 可能会很陌生,究竟它有什么特点,我怎么用呢?
    # ubuntu at lazybox in ~/html [8:09:36]
    → echo "Hello, World" > index.html
    
    # ubuntu at lazybox in ~/html [8:09:45]
    → touch Procfile
    
    # ubuntu at lazybox in ~/html [8:19:31]
    → ls
    index.html  Procfile
    # ubuntu at lazybox in ~/html [8:19:42]
    → cf p index
    Creating app index in org system / space dev as admin...
    OK
    
    Creating route index.cf.cloud...
    OK
    
    Binding index.cf.cloud to index...
    OK
    
    Uploading index...
    Uploading app files from: /home/ubuntu/html
    Uploading 270B, 2 files
    Done uploading
    OK
    
    Starting app index in org system / space dev as admin...
    Downloading staticfile_buildpack...
    Downloading go_buildpack...
    Downloading dotnet_core_buildpack...
    Downloading binary_buildpack...
    Downloading php_buildpack...
    Downloaded staticfile_buildpack
    Downloading java_buildpack...
    Downloaded binary_buildpack
    Downloading nodejs_buildpack...
    Downloaded dotnet_core_buildpack
    Downloading python_buildpack...
    Downloaded go_buildpack
    Downloading ruby_buildpack...
    Downloaded php_buildpack
    Downloaded nodejs_buildpack
    Downloaded python_buildpack
    Downloaded java_buildpack
    Downloaded ruby_buildpack
    Creating container
    Successfully created container
    Downloading app package...
    Downloaded app package (270B)
    Staging...
    -----> Staticfile Buildpack version 1.4.11
    -----> Installing nginx
           Using nginx version 1.13.3
    -----> Installing nginx 1.13.3
           Download [https://buildpacks.cloudfoundry.org/dependencies/nginx/nginx-1.13.3-linux-x64-53917f43.tgz]
    -----> Root folder /tmp/app
    -----> Copying project files into public
    -----> Configuring nginx
    Exit status 0
    Staging complete
    Uploading droplet, build artifacts cache...
    Uploading build artifacts cache...
    Uploading droplet...
    Uploaded build artifacts cache (220B)
    Uploaded droplet (2.6M)
    Uploading complete
    Stopping instance 0aa6692c-8647-4561-9294-ae5c434c21c8
    Destroying container
    Successfully destroyed container
    
    1 of 1 instances running
    
    App started
    
    
    OK
    
    App index was started using this command `$HOME/boot.sh`
    
    Showing health and status for app index in org system / space dev as admin...
    OK
    
    requested state: started
    instances: 1/1
    usage: 1G x 1 instances
    urls: index.cf.cloud
    last uploaded: Fri Aug 18 08:19:49 UTC 2017
    stack: cflinuxfs2
    buildpack: staticfile 1.4.11
    
         state     since                    cpu    memory       disk         details
    #0   running   2017-08-18 08:20:29 AM   0.0%   3.7M of 1G   7.1M of 1G
    
    # ubuntu at lazybox in ~/html [8:20:37]
    →  curl index.cf.cloud
    Hello, World
    
    

    很简单, 简单的一个push 命令就可以将站点发布.

    如果你想了解这和OpenStack是怎么关联起来的, 让我们看下这个

    bosh-vms

    没错,这些实例就构成了PaaS 平台, 你可能会疑问api,cc-bridge, blabla, ....这些都是什么啊? 没关系,这些组件在之后都会有说明.

    到目前为止还没有提到OpenStack啊.
    让我们看一张这个图

    Bluebox power OpenStack
    这张图很熟悉了吧,从这里可以看到所有创建出来的VM 信息.
    再看一下网络图谱图
    这里写图片描述

    相信到目前为止已经对OpenStack 和CloudFoundry 有了初步的感受,再接下来的文章里,会介绍如何step-by-step搭建这样的一套云平台

    发布在 Blogs •
    OpenStack 之使用Ansible部署AIO环境

    如果你是OpenStack 的developer的话,那么相信对DevStack的会十分的熟悉。 DevStack 可以在一台机器上快速的交付AIO(all-in-one)的OpenStack环境十分的方便。 OpenStack-Ansible 是一种通过ansible来部署OpenStack 环境的方案,具体的设计初衷、以及如果使用请参考rackspace 以及platform9开发博客

    物理环境

    名称 信息
    OS Dist Ubuntu 16.04.2 LTS
    Disk 1T + 2T sata 盘
    Mem 32G
    CPU Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
    sdb             8:16   0 931.5G  0 disk
    ├─sdb1          8:17   0   243M  0 part
    ├─sdb2          8:18   0     1K  0 part
    └─sdb5          8:21   0 931.3G  0 part
      ├─dvlp-root 252:0    0    78G  0 lvm  /
      ├─dvlp-home 252:1    0 262.3G  0 lvm  /home
      └─dvlp-data 252:2    0 553.7G  0 lvm
    sdc             8:32   0   1.8T  0 disk /openstack
    
    • 2T盘用于存储OpenStack相关的数据
    • 1T盘操作系统相关数据盘

    在使用时遇到的问题在此说明

    1. 安装时启动的lxc container 无法获得private ip
      正常情况下在执行了ansible 相关命令后应该每一个container应该有内网及外网IP, 如下
    → sudo lxc-ls -f
    NAME                                        STATE   AUTOSTART GROUPS            IPV4                                          IPV6
    aio1_cinder_api_container-f3bdb579          RUNNING 1         onboot, openstack 10.255.255.244, 172.29.236.67, 172.29.247.153 -
    aio1_cinder_scheduler_container-25e9e567    RUNNING 1         onboot, openstack 10.255.255.198, 172.29.238.236                -
    aio1_designate_container-b3ca6e11           RUNNING 1         onboot, openstack 10.255.255.64, 172.29.239.241                 -
    aio1_galera_container-59168dd6              RUNNING 1         onboot, openstack 10.255.255.172, 172.29.236.218                -
    aio1_glance_container-e43dfd64              RUNNING 1         onboot, openstack 10.255.255.176, 172.29.237.35, 172.29.247.172 -
    aio1_heat_apis_container-9008349f           RUNNING 1         onboot, openstack 10.255.255.112, 172.29.238.189                -
    aio1_heat_engine_container-2d62ff94         RUNNING 1         onboot, openstack 10.255.255.25, 172.29.239.228                 -
    aio1_horizon_container-2a77938a             RUNNING 1         onboot, openstack 10.255.255.74, 172.29.239.99                  -
    aio1_keystone_container-3441527b            RUNNING 1         onboot, openstack 10.255.255.28, 172.29.236.169                 -
    aio1_memcached_container-43bf9c7f           RUNNING 1         onboot, openstack 10.255.255.238, 172.29.239.33                 -
    aio1_neutron_agents_container-31363c11      RUNNING 1         onboot, openstack 10.255.255.187, 172.29.236.66, 172.29.242.144 -
    aio1_neutron_server_container-c6d33080      RUNNING 1         onboot, openstack 10.255.255.160, 172.29.236.141                -
    aio1_nova_api_metadata_container-b04322cb   RUNNING 1         onboot, openstack 10.255.255.203, 172.29.237.253                -
    aio1_nova_api_os_compute_container-53803a56 RUNNING 1         onboot, openstack 10.255.255.61, 172.29.237.166                 -
    aio1_nova_api_placement_container-d09947c4  RUNNING 1         onboot, openstack 10.255.255.22, 172.29.236.157                 -
    aio1_nova_conductor_container-e9e82699      RUNNING 1         onboot, openstack 10.255.255.120, 172.29.239.36                 -
    aio1_nova_console_container-2517dd0e        RUNNING 1         onboot, openstack 10.255.255.54, 172.29.239.129                 -
    aio1_nova_scheduler_container-db02b5f9      RUNNING 1         onboot, openstack 10.255.255.243, 172.29.237.239                -
    aio1_rabbit_mq_container-66fd8455           RUNNING 1         onboot, openstack 10.255.255.2, 172.29.236.124                  -
    aio1_repo_container-cf8b6b77                RUNNING 1         onboot, openstack 10.255.255.17, 172.29.238.136                 -
    aio1_rsyslog_container-d461d2ed             RUNNING 1         onboot, openstack 10.255.255.76, 172.29.236.228                 -
    aio1_swift_proxy_container-00c23b79         RUNNING 1         onboot, openstack 10.255.255.20, 172.29.236.166, 172.29.245.74  -
    aio1_utility_container-9755697d             RUNNING 1         onboot, openstack 10.255.255.219, 172.29.239.126                -
    ubuntu-xenial-amd64                         STOPPED 0         -                 -                                             -
    
    

    由于之前配置了dnsmasq作为本机的dns server,而lxc 需要用dnsmasq作为所启动的container的dhcp 服务器,所以container 无法通过dhcp获得ip导致deploy失败

    解决办法: 清空dnsmasq的配置后,重新deploy container 即可获得内部IP

    1. 重启物理节点后无法识别usb设备

    在OpenStack-Ansible 的使用文档中说明了如何处理在重启物理节点后,openstack 服务如何恢复的问题。在使用时,由于sdc盘通过的usb 接口连接到的server中,重启后出现无法识别存储设备的问题。
    在ansible 的role 里面有security、security role 相关的设置,在安装好openstack-ansible 后会在host中使用modporb禁用了USB设备

    → cat /etc/modprobe.d/openstack-ansible-security-disable-usb-storage.conf
    install usb-storage /bin/true
    

    解决办法: 删除此文件后,重启物理节点,usb设备即可识别

    发布在 Blogs •
    CloudFoundry - 从AdminUI中查看数据

    什么是AdminUI?

    官方解释

    An application for viewing Cloud Foundry metrics and operations data.

    是一个可以从cloudfoundry 平台里面读取各个component以及操作数据的应用,做社区孵化中的项目已经存在了很长时间了,对运维人员来说,通过adminui 可以看到目前平台中的关键数据

    除了通过web 界面访问admui 之外,也可以通过adminui中内置的nats client library 直接读取nats中各个component发出来的数据

    nats_server=`grep "nats:" /var/vcap/jobs/admin_ui_v2/config/config.yml | head -n 1 | cut -d " " -f 2`
    nats_dir=`find /var/vcap/packages/admin_ui_v2/admin_ui_v2/vendor/bundle// -type d -name bin | grep nats`
    ruby_dir=`find /var/vcap/packages/ruby*/bin -type d`
    ruby_version=`ls /var/vcap/packages/admin_ui_v2/admin_ui_v2/vendor/bundle/ruby/`
    export PATH=$nats_dir:$ruby_dir:$PATH
    export GEM_PATH=/var/vcap/packages/admin_ui_v2/admin_ui_v2/vendor/bundle/ruby/$ruby_version:$GEM_PATH
    nats-sub $topic -s $nats_server

    topic 根据需要传递参数即可

    总结

    虽然adminui 好用,但是依赖于nats 去读取各个component的数据,在diego 以及新版本的cf-release中,社区在对各个component 进行改造, 直接通过rest api 调用,而且adminui 做的还是相对比较粗糙、功能还是有限。更多的像adminui之类的ops 管理工具都是各个公司按照各自需求定制开发, 有能里的朋友去社区多提PR 吧

    发布在 Blogs •
    git 使用技巧之使用不同的private key 操作工程

    在使用git的过程当中因为要操作多个工程,需要为不同的project设置不同的用户,可以通过以下方式来进行设置

    配置 ~/.ssh/config 全局设置

    此方法适用于修改所有的project的git 配置

    host github.com
    HostName github.com
    IdentityFile ~/.ssh/id_rsa_github
    User git

    Environment variable GIT_SSH_COMMAND

    从git 2.3.0 版本开始,可以使用环境变量 GIT_SSH_COMMAND 来进行配置

    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example" git clone example

    注意 -i 参数有时会被config文件锁覆盖,在这种情况下提供空的SSH config 文件可以解决

    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example -F /dev/null" git clone example

    在Git 2.10.0 版本开始,可以对每一个project 或者全局的设置git 信息, 不再需要设置环境变量配置 core.sshCommand

    git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -F /dev/null"
    git pull
    git push

    发布在 Blogs •
    ansible 使用技巧总结

    Ansible 有很多的使用场景:

    1. 以命令行方式执行单一的task
    2. 通过ansible-playbook 来执行playbbook
    3. 使用发行版tower管理、运行playbook
    4. 以及使用开源版本的semphore 来替换tower
      以下命令,列举出了在使用ansible-playbook时的技巧
    1. Syntax checking

      $ ansible-playbook --syntax-check oraclejdk-destroy.yml
      ERROR! Syntax Error while loading YAML.

      The error appears to have been in '/home/liquidat/Gits/github/>ansible-demo-oraclejdk/oracle-windows-destroy.yml': line 10, column 11,
      but may be elsewhere in the file depending on the exact syntax problem.

      The offending line appears to be:

      win_template: src=data/remove-program.j2 dest=C:\temp\remove-program.ps1

      • name: remove application
        ^ here
    2. Listing affected hosts

      $ ansible-playbook --list-hosts oraclejdk-destroy.yml

      playbook: oraclejdk-destroy.yml

      play #1 (windows): remove OracleJDK on Windows TAGS: []
      pattern: [u'windows']
      hosts (1):
      radon

      play #2 (rhel): remove OracleJDK on RHEL TAGS: []
      pattern: [u'rhel']
      hosts (2):
      neon
      helium
      ...

    3. List tasks

      $ ansible-playbook --list-tasks oraclejdk-destroy.yml

      playbook: oraclejdk-destroy.yml

      play #1 (windows): remove OracleJDK on Windows TAGS: []
      tasks:
      copy Java remove script to temp TAGS: []
      remove application TAGS: []
      remove temp dir in Windows TAGS: []

      play #2 (rhel): remove OracleJDK on RHEL TAGS: []
      tasks:
      remove java dir TAGS: []
      ...

    4. List all tags

      $ ansible-playbook --list-tags setup-control.yml

      playbook: setup-control.yml

      play #1 (tuzak): TAGS: []
      TASK TAGS: [base_setup, db, imap, ldap, mail, oc, smtp]
      ...

    5. Running in test mode

      ansible-playbook --check oraclejdk-setup.yml

      PLAY [set up OracleJDK on Windows]
      TASK [setup]
      ok: [radon]

      TASK [set up temp dir in Windows] **********************************************

      ....

    6. Starting playbooks in the middle

      nsible-playbook --start-at-task="run exe installer" oraclejdk-setup.yml

      PLAY [set up OracleJDK on Windows] *********************************************

      TASK [setup] *******************************************************************
      ok: [radon]

      TASK [run exe installer] *******************************************************
      ok: [radon]
      ...

    7. Showing diffs

      $ ansible-playbook --diff examples/template.yml

      PLAY [template example] ********************************************************

      TASK [setup] *******************************************************************
      ok: [helium]

      TASK [copy template] ***********************************************************
      changed: [helium]
      --- before: /tmp/template.conf
      +++ after: dynamically generated
      @@ -1,2 +1,3 @@
      hostname: ansible-demo-helium
      -bumble: bee
      +foo: bar
      +MX: 10 mx2.redhat.com.,5 mx1.redhat.com.

      PLAY RECAP *********************************************************************
      helium : ok=2 changed=1 unreachable=0 failed=0

    发布在 Blogs •
    tinc installation guide
    1. server & client
      install tinc

    2. c/S

      mkdir -p /etc/tinc/yajump
      mkdir /etc/tinc/yajump/hosts

    3. S
      vim /etc/tinc/yajump/tinc.conf

       Name = yajump
       Device = /dev/net/tun
       AddressFamily = ipv4
       Interface = tun1
      

      vim /etc/tinc/yajump/tinc-up

       #!/bin/sh
       ip link set $INTERFACE up
       ip addr add  192.168.100.1/32 dev $INTERFACE
       ip route add 192.168.100.0/24 dev $INTERFACE
      

      vim /etc/tinc/yajump/tinc-down

       #!/bin/sh
       ip route del 192.168.100.0/24 dev $INTERFACE
       ip addr del 192.168.100.1/32 dev $INTERFACE
       ip link set $INTERFACE down
      

      chmod +x /etc/tinc/yajump/tinc-up
      chmod +x /etc/tinc/yajump/tinc-down

    4. Client
      vim /etc/tinc/yajump/tinc.conf

       Name = yajump-client
       Device = /dev/net/tun
       ConnectTo = yajump
       Interface = tun0
      

      vim /etc/tinc/yajump/tinc-up

       #!/bin/sh
       ip link set $INTERFACE up
       ip addr add  192.168.100.100/32 dev $INTERFACE
       ip route add 192.168.100.0/24 dev $INTERFACE
      

      vim /etc/tinc/yajump/tinc-down

       #!/bin/sh
       ip route del 192.168.100.0/24 dev $INTERFACE
       ip addr del 192.168.100.100/32 dev $INTERFACE
       ip link set $INTERFACE down
      

      chmod +x /etc/tinc/yajump/tinc-up
      chmod +x /etc/tinc/yajump/tinc-down

    5. 在服务器上建立host配置文件并生成密钥:
      vim /etc/tinc/yajump/hosts/yajump 请将address替换为服务器的公网IP

       Address = 139.59.251.158
       Port = 6155
       Subnet 192.168.100.1/32
       Subnet 0.0.0.0/0
      

      生成秘要

       tincd -n yajump -K
      
    6. 在客户上建立host配置文件并生成密钥:

      vim /etc/tinc/yajump/hosts/yajumpclient

       Port = 6155
       Subnet = 192.168.100.100/32
      

      生成秘要

       tincd -n yajump -K
      

    6.1. 配置Openwrt下的tinc的启动文件 /etc/config/tinc

    config tinc-net yajump
        option enabled 1
        option logfile /tmp/log/tinc.yajump.log
        option debug 3
        option AddressFamily ipv4
        list ConnectTo yajump
        option Interface tun0
        option Name yajumpclient
        option PrivateKeyFile /etc/tinc/yajump/rsa_key.priv
    
    config tinc-host yajumpclient
        option enabled 1
        option net yajump
        option Port 6155
        option Subnet 192.168.100.0/24
    
    1. 将Server 与 Client 的host 进行分发到对方相同的目录中
    2. Server 启动tinc: tincd -n yajump -D -d3
    3. Client 启动tinc: /etc/init.d/tinc start

    Install chinadns as the secure dns server

    发布在 Blogs •
    • 1
    • 2
    • 1 / 2