K8S之traefik

Traefik

Traefik是一个用Golang开发的轻量级的Http反向代理和负载均衡器。由于可以自动配置和刷新backend节点,目前可以被绝大部分容器平台支持,例如Kubernetes,Swarm,Rancher等。由于traefik会实时与Kubernetes API交互,所以对于Service的节点变化,traefik的反应会更加迅速。总体来说traefik可以在Kubernetes中完美的运行.

Traefik 还有很多特性如下:

  • 速度快
  • 不需要安装其他依赖,使用 GO 语言编译可执行文件
  • 支持最小化官方 Docker 镜像
  • 支持多种后台,如 Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS 等等
  • 支持 REST API
  • 配置文件热重载,不需要重启进程
  • 支持自动熔断功能
  • 支持轮训、负载均衡
  • 提供简洁的 UI 界面
  • 支持 Websocket, HTTP/2, GRPC
  • 自动更新 HTTPS 证书
  • 支持高可用集群模式

接下来我们使用 Traefik 来替代 Nginx + Ingress Controller 来实现反向代
理和服务暴漏。

那么二者有什么区别呢?简单点说吧,在 Kubernetes 中使用 nginx 作为前端负载均衡,通过 Ingress Controller 不断的跟 Kubernetes API 交互,实时获取后端 Service、Pod 等的变化,然后动态更新 Nginx 配置,并刷新使配置生效,来达到服务自动发现的目的,而 Traefik 本身设计的就能够实时跟 Kubernetes API 交互,感知后端 Service、Pod 等的变化,自动更新配置并热重载。大体上差不多,但是 Traefik 更快速更方便,同时支持更多的特性,使反向代理、负载均衡更直接更高效。

1.Role Based Access Control configuration (Kubernetes 1.6+ only)

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

授权,官方文档不懂下下来看文档

2.Deploy Træfik using a Deployment or DaemonSet

To deploy Træfik to your cluster start by submitting one of the YAML files to the cluster with kubectl:

kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-deployment.yaml   此模板有些问题,我先用ds模板

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

deployment和ds的区别:ds会在每台node上都创造一个pod.而deploy是人为控制的副本。如果几台很多了,没有必要用ds,比如100台 会造100个pod,没有意义。自己用ds模板改下,kind: Deployment

如下

直接找到DS模板吧kind改成deploy模式
kind: Deployment

3.Check the Pods

# kubectl --namespace=kube-system get pods -o wide 
traefik-ingress-controller-79877bbc66-p29jh 1/1 Running 0 32m   10.249.243.182    k8snode2-175v136​

查找一下在那台服务器上,deploy会随机分配一台服务器

4.Ingress and UI

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

自己再造个web测试用

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  template:
    metadata:
      labels:
        name: nginx-svc
        namespace: default
spec:
  selector:
    run: ngx-pod
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: ngx-pod
spec:
  replicas: 4
  template:
    metadata:
      labels:
        run: ngx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        ports:
        - containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ngx-ing
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: www.ha.com
    http:
      paths:
      - backend:
          serviceName: nginx-svc
          servicePort: 80

5.测试成功

未分类

6.HTTPS证书

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: traefik-ui.minikube
    http:
      paths:
      - backend:
          serviceName: traefik-web-ui
          servicePort: 80
  tls:
   - secretName: traefik-ui-tls-cert

官方是怎么导入证书的呢? 注:key和crt必须要有

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=traefik-ui.minikube"
kubectl -n kube-system create secret tls traefik-ui-tls-cert --key=tls.key --cert=tls.crt

7.Basic Authentication

A. Use htpasswd to create a file containing the username and the MD5-encoded password:
htpasswd -c ./auth myusername
You will be prompted for a password which you will have to enter twice. htpasswd will create a file with the following:
cat auth
myusername:$apr1$78Jyn/1K$ERHKVRPPlzAX8eBtLuvRZ0
B. Now use kubectl to create a secret in the monitoring namespace using the file created by htpasswd
kubectl create secret generic mysecret --from-file auth --namespace=monitoring
Note
Secret must be in same namespace as the Ingress object.
C. Attach the following annotations to the Ingress object:
    ingress.kubernetes.io/auth-type: "basic"
    ingress.kubernetes.io/auth-secret: "mysecret"
They specify basic authentication and reference the Secret mysecret containing the credentials.
Following is a full Ingress example based on Prometheus:
#配置文件如下
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: prometheus-dashboard
 namespace: monitoring
 annotations:
   kubernetes.io/ingress.class: traefik
   ingress.kubernetes.io/auth-type: "basic"
   ingress.kubernetes.io/auth-secret: "mysecret"
spec:
 rules:
 - host: dashboard.prometheus.example.com
   http:
     paths:
     - backend:
         serviceName: prometheus
         servicePort: 9090

模板1 多域名暴漏端口:再看一下 UI 页面,立马更新过来,可以看到刚刚配置的 dashboard.k8s.traefik 和 ela.k8s.traefik

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-ela-k8s-traefik
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: dashboard.k8s.traefik
    http:
      paths:
      - path: /  
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
  - host: ela.k8s.traefik
    http:
      paths:
      - path: /  
        backend:
          serviceName: elasticsearch-logging
          servicePort: 9200

模板2

注意:这里我们根据路径来转发,需要指明 rule 为 PathPrefixStrip,配置为 traefik.frontend.rule.type: PathPrefixStrip

再看一下 UI 页面,也是立马更新过来,可以看到刚刚配置的 my.k8s.traefik/dashboard 和 my.k8s.traefik/kibana

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-k8s-traefik
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.frontend.rule.type: PathPrefixStrip
spec:
  rules:
  - host: my.k8s.traefik
    http:
      paths:
      - path: /dashboard
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
      - path: /kibana
        backend:
          serviceName: kibana-logging
          servicePort: 5601

8.自动熔断

在集群中,当某一个服务大量出现请求错误,或者请求响应时间过久,或者返回500+错误状态码时,我们希望可以主动剔除该服务,也就是不在将请求转发到该服务上,而这一个过程是自动完成,不需要人工执行。Traefik 通过配置很容易就能帮我们实现,Traefik 可以通过定义策略来主动熔断服务。

  • NetworkErrorRatio() > 0.5:监测服务错误率达到50%时,熔断。
  • LatencyAtQuantileMS(50.0) > 50:监测延时大于50ms时,熔断。
  • ResponseCodeRatio(500, 600, 0, 600) > 0.5:监测返回状态码为[500-600]在[0-600]区间占比超过50%时,熔断。

案例

apiVersion: v1
kind: Service
metadata:
  name: wensleydale
  annotations:
    traefik.backend.circuitbreaker: "NetworkErrorRatio() > 0.5" 

9.官方文档:

其他多看官方文档

https://docs.traefik.io/user-guide/kubernetes/

10.update

由于业务需求,node会扩充, ds模式多了会浪费资源 20台node+,我们怎么把traefik固定在几台机器上。查了一些文档找到了这个解决方法。

给node打标签,用ds模式启动标签化节点 :https://www.kubernetes.org.cn/daemonset 参考文档。

案例:

给三台node打标签

kubectl label nodes k8snode1-174v136-taiji traefik=svc
kubectl label nodes k8snode2-175v136-taiji traefik=svc
kubectl label nodes k8snode3-176v136-taiji traefik=svc​
查看标签
[root@k8s-m1 Traefik]# kubectl get nodes --show-labels
NAME                     STATUS    ROLES     AGE       VERSION   LABELS
k8snode1-174v136-taiji   Ready     node      42d       v1.10.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=k8snode1-174v136-taiji,node-role.kubernetes.io/node=,traefik=svc
[root@k8s-m1 Traefik]# cat traefik-ds.yaml 
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress-lb
spec:
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      nodeSelector:
        traefik: "svc"            #重点2行
...................
验证
[root@k8s-m1 Traefik]# kubectl get ds -n kube-system 
NAME                         DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR  
traefik-ingress-controller   3         3         3         3            3           traefik=svc

总结:后期可以根据业务量加标签扩展traefik节点

k8s与数据分析–利用redash做自助数据分析

前言

在之前文章中,一直讲prometheus的metrics以及apm的指标的重要性,多侧重于收据的收集和存储。如果不对这些数据进行数据分析,那么就没有收集的意义了。通过数据分析和挖掘,让数据产生价值。一直以来我认为devops必须是一个闭环,即apm,日志,监控着三大系统的数据,必须经过分析对dev和ops有价值。
数据可视化是大数据的『最后一公里』,做好可视化是对于数据分析是重要的。
今天,主要介绍redash这款数据分析的利器。

redash简介

redash是一款开源的BI工具,提供了基于web的数据库查询和数据可视化功能。

未分类

支持 SQL, NoSQL, Big Data and API data等20几种常见的数据源:

未分类

基本上满足了大多数的场景。相比
superset,除了上手简单,支持influxdb等时序数据库。这点对于监控数据分析很有优势。

sql友好的SQL editor,更加高效的编写复杂的sql

未分类

随时写,随时查,实时看到查询的效果

  • 支持丰富的可视化展示形式
    • Boxplot
    • Chart – Line, Bar, Area, Pie, Scatter
    • Cohort
    • Counter
    • Funnel
    • Map
    • Pivot Table
    • Sankey
    • Sunburst
    • Word Cloud

未分类

角色权限相关,支持ldap等,方便与企业内部的用户体系打通。

安装和简单使用

安装

如果是想直接体验的话,docker-compose部署最简单,redashgithub仓库中直接提供了docker-compose.production.yml文件,直接docker-compose up -d 即可。

# This is an example configuration for Docker Compose. Make sure to atleast update
# the cookie secret & postgres database password.
#
# Some other recommendations:
# 1. To persist Postgres data, assign it a volume host location.
# 2. Split the worker service to adhoc workers and scheduled queries workers.
version: '2'
services:
  server:
    image: redash/redash:latest
    command: server
    depends_on:
      - postgres
      - redis
    ports:
      - "5000:5000"
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      REDASH_COOKIE_SECRET: veryverysecret
      REDASH_WEB_WORKERS: 4
    restart: always
  worker:
    image: redash/redash:latest
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      QUEUES: "queries,scheduled_queries,celery"
      WORKERS_COUNT: 2
    restart: always
  redis:
    image: redis:3.0-alpine
    restart: always
  postgres:
    image: postgres:9.5.6-alpine
    # volumes:
    #   - /opt/postgres-data:/var/lib/postgresql/data
    restart: always
  nginx:
    image: redash/nginx:latest
    ports:
      - "80:80"
    depends_on:
      - server
    links:
      - server:redash
    restart: always

通过compose文件可以看出,redash依赖redis和pgsql数据库。redis用来缓存一些查询result,而pgsql是元数据库,目前不支持mysql替换pgsql。

其他安装方式,见官方文档https://redash.io/help/open-source/setup

简单使用

先上一张实际的效果图:

未分类

包含了couter和area chart。
数据源包括influxdb时序数据库,和mysql业务库。

未分类

其中audit-middware 其实是Query Results库。Query Results Data Source 允许你在一些已经存在的查询结果之上再做一些高级的查询, 这样就可以轻易合并一些查询结果。

总结

在实际使用中,redash和superset各有优劣。根据自己的场景来选择吧。查阅资料的过程中,已经有人对redash做了二次开发,这也许是深度使用的必经之路。
为什么非要使用这种开源BI可视化工具?
因为如果是前后端配合的话,工作量会很大。而且也很难实现随时修改随时上线。不过这取决于前期数据的完整性。

面向业务开发者的 k8s 基本命令

随着容器技术的发展,k8s 也越来越火热。在网络上有许多关于 k8s 的文章,但大部分都是关于集群部署相关的,

而这篇文章主要讲作为应用开发者如何使用 k8s 。

github: https://github.com/shfshanyue/blog/tree/master/Articles/Kubenetes-Commands

准备

预备知识

Docker,学习 k8s 之前了解 Docker 是毋庸置疑的。

工具

brew install kubectl

kubectl 是 k8s 的命令行工具,用于管理 k8s 集群。以上是 Mac 下的安装方法,其它操作系统参考官方文档。当然,你也可以使用 Dashboard 管理容器。

Cluster

k8s 集群,一般生产环境有一个 Cluster 集群,测试环境有一个 Cluster 集群。

Namespace

在一个 Cluster 会有不同的 Namespace,可以区分不同的业务团队。

Pod

Pod 是 k8s 中最小的可部署单元。一般一个 Pod 运行一个 Container,但是有时也会运行多个 Container。类似 docker-compose。

Deployment

Deployment 用来控制 Pod,比如控制一个应用起几个 Pod。

配置文件

关于 k8s 的配置文件位置在 ~/.kube/config。另外也可以使用命令 kubectl config 查看以及更改配置,使用命令更改配置的同时,配置文件也会改变。

配置文件可以指定 Cluster,Namespace,User 的配置,并设置 Context。以下是一个简版的配置文件。

# 该配置文件配置了一个用户 shanyue,一个集群 dev,并且设置了 dev 的 context
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /Users/shanyue/.minikube/ca.crt
    server: https://192.168.99.100:8443
  name: dev
contexts:
- context:
    cluster: dev
    namespace: Business
    user: shanyue
  name: dev
current-context: dev
kind: Config
preferences: {}
users:
- name: shanyue
  user:
    client-certificate: /Users/shanyue/.minikube/client.crt
    client-key: /Users/shanyue/.minikube/client.key

其中 current-context 代表当前上下文,也可以通过以下命令来设置上下文。

# 查看配置
kubectl config view

# 查看集群列表
kubectl config get-clusters

# 查看 Context 列表
kubectl config get-contexts

# 设置当前 Context
kubectl config use-context dev

创建资源

kubectl create 代表根据文件创建资源,可以是 Deployment,也可以是 Pod。

kubectl run 代表根据镜像创建资源。

kubectl create -f app.yaml

kubectl run --image=k8s.gcr.io/echoserver:1.10 --port=8080

一般在 CI 中作 deploy 时会使用 kubectl apply 命令,根据配置文件更新资源。

配置文件中可以写多份配置,也可以写 Deployment,Service 各种 Kind 配置。以下是以 node 作为服务器语言样例的配置。

apiVersion: v1
kind: Service
metadata:
  name: app
  namespace: dev
  labels:
    name: app
spec:
  ports:
  - port: 8080
    targetPort: 8080
    protocol: TCP
  selector:
    name: app

---

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app
  namespace: dev
  labels:
    name: app
spec:
  template:
    metadata:
      labels:
        name: app
    spec:
      containers:
      - name: app
        image: node
        imagePullPolicy: Always
        env:
        - name: PORT
          value: "8080"
        ports:
        - containerPort: 8080

访问资源

以下 $app 代表特定 Pod 的 Name

# 获取当前 Context 下所有的 Deployment
kubectl get deployments

# 获取当前 Context 下所有的 Pod
kubectl get pods

# 获取当前 Cluster 下所有的 Pod
kubectl get pods --all-namespaces

# 获取特定 Pod 的状态
kubectl describe pod $app

# 进入某个 Pod 容器里边的命令行
kubectl exec -it $app bash

# 查看某个 Pod 的日志
kubectl logs $app

Linux安全-使用iptables封掉所有邮件端口

说明:封掉邮件端口可以防止垃圾邮件

方法

1、直接封掉所有邮件协议端口

iptables -A INPUT -p tcp -m multiport --dport 25,110,465:587,993:995 -j DROP
iptables -A INPUT -p udp -m multiport --dport 25,110,465:587,993:995 -j DROP
iptables -A OUTPUT -p tcp -m multiport --dport 25,110,465:587,993:995 -j DROP
iptables -A OUTPUT -p udp -m multiport --dport 25,110,465:587,993:995 -j

2、保存iptables设置

iptables-save
service iptables save

自建 Laravel 的 Docker 开发环境

好久没写东西,今天说一说怎么自建一个 Laravel 运行的 Docker 环境。
市面上最出名的莫过于「laradock」https://github.com/laradock/laradock

未分类

Docker PHP development environment.
使用参考:http://laradock.io/

既然是「自建」,那我们可以参考这个,最小化满足 Laravel 运行的需要。

下面是我罗列出的基本条件:

  1. 软件:PHP 7.2、Nginx、MySQL、Composer、NPM or Yarn 等等;
  2. 使用国内镜像;使用国内镜像;使用国内镜像;
  3. 易于扩展使用,如随时可以切换 PHP 版本,或者 Apache 和 Nginx 切换使用。

Docker-Compose

要达到可扩展行,和「laradock」一样,使用 Docker-Compose 编排的方式,将核心的几个 image 组装在一起。

php-fpm

这里我们使用的是「DaoCloud」加速镜像 —— 7.2-fpm-alpine。

该版本既用 PHP 7.2 版本,而且 alpine 最小化系统,可以基于此,安装环境需要的额外工具:如,composer、nodejs、python、yarn 等。
FROM daocloud.io/php:7.2-fpm-alpine

MAINTAINER coding01 <[email protected]>

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

RUN apk add --no-cache --virtual .build-deps 
        $PHPIZE_DEPS 
        curl-dev 
        imagemagick-dev 
        libtool 
        libxml2-dev 
        postgresql-dev 
        sqlite-dev 
    && apk add --no-cache 
        curl 
        git 
        imagemagick 
        mysql-client 
        postgresql-libs 
    && pecl install imagick 
    && docker-php-ext-enable imagick 
    && docker-php-ext-install 
        curl 
        iconv 
        mbstring 
        pdo 
        pdo_mysql 
        pdo_pgsql 
        pdo_sqlite 
        pcntl 
        tokenizer 
        xml 
        zip 
    && curl -s https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin/ --filename=composer 
    && apk del -f .build-deps

# 修改 composer 为国内镜像
RUN composer config -g repo.packagist composer https://packagist.laravel-china.org

# install prestissimo
RUN composer global require "hirak/prestissimo"

# install laravel envoy
RUN composer global require "laravel/envoy"

#install laravel installer
RUN composer global require "laravel/installer"

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

RUN apk update && apk add -u nodejs libpng-dev python

ENV PATH /root/.yarn/bin:$PATH

RUN apk update 
  && apk add curl bash binutils tar 
  && rm -rf /var/cache/apk/* 
  && /bin/bash 
  && touch ~/.bashrc 
  && curl -o- -L https://yarnpkg.com/install.sh | bash 
  && yarn config set registry 'https://registry.npm.taobao.org' 
  && npm install -g cnpm --registry=https://registry.npm.taobao.org

WORKDIR /var/www

其中安装 alpine 系统插件,我们使用 mirrors.aliyun.com 阿里云镜像。

php:7.2-fpm-alpine 具体使用,可以参考:dashboard.daocloud.io/packages/01…

nginx

我们使用 nginx,主要是将网站的配置文件载入 nginx 中。

FROM daocloud.io/nginx:1.13-alpine

MAINTAINER coding01 <[email protected]>

ADD vhost.conf /etc/nginx/conf.d/default.conf

WORKDIR /var/www

剩下就是连接这些 images。最后看看 docker-compose.yml 文件内容:

version: '2'
services:

  # The Application
  app:
    build:
      context: ./
      dockerfile: app.dockerfile
    working_dir: /var/www
    volumes:
      - ../:/var/www
    environment:
      - "DB_PORT=3306"
      - "DB_HOST=database"
      - "REDIS_HOST=redis"
      - "REDIS_PORT=6379"

  # The Web Server
  web:
    build:
      context: ./
      dockerfile: web.dockerfile
    working_dir: /var/www
    volumes_from:
      - app
    ports:
      - 8080:80

  # The Database
  database:
    image: daocloud.io/mysql:5.7.4
    volumes:
      - dbdata:/var/lib/mysql
    environment:
      - "MYSQL_DATABASE=homestead"
      - "MYSQL_USER=homestead"
      - "MYSQL_PASSWORD=secret"
      - "MYSQL_ROOT_PASSWORD=secret"
    ports:
        - "3306:3306"

  redis:
    image: daocloud.io/library/redis:4.0.10-alpine
    command: redis-server --appendonly yes

volumes:
  dbdata:

测试一遍

创建 Laravel 项目

composer create-project laravel/laravel demo

注:为了做测试,可以将 vendor 文件夹和 composer.lock 文件删除。

git clone

在 demo 项目相同文件夹下,git clone 我们自建的「laraveldocker」:
git clone https://github.com/fanly/laraveldocker.git

修改 docker-compose.yml

将 docker-compose.yml 文件的路径执行我们的项目:

app:
    build:
      context: ./
      dockerfile: app.dockerfile
    working_dir: /var/www
    volumes:
      - ../:/var/www

build

在 laraveldocker 下执行构建命令:

docker-compose up

未分类

整个速度还是蛮快的

未分类

接下来进入容器内

docker exec -it de075c525528 bash

我们看看安装插件的效果:

未分类

使用的是 https://packagist.laravel-china.org 国内镜像。

注:该镜像是由 Laravel China 社区联合 又拍云 与 优帆远扬 共同合作推出的公益项目,旨在为广大 PHP 用户提供稳定和高速的 Composer 国内镜像服务。

值得推荐使用

参考:laravel-china.org/topics/4484…

使用 yarn 或者 cnpm 安装插件:

未分类

生成 Laravel key secret:

cp .env.example .env
php artisan key:generate

Application key [base64:4A7VK6MEX7FakPLDSLji97kz/nyWUAWhW4wYn3gefsY=] set successfully.

运行下看看效果吧:

未分类

我们接下来看看数据库连接吧,修改 .env:

DB_CONNECTION=mysql
DB_HOST=database
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

我们使用 php artisan make:auth 来生成布局、注册和登录视图以及所有的认证接口的路由。同时它还会生成 HomeController 来处理应用的登录请求。使用 php artisan migrate 来载入数据。

未分类

我们看看数据表:

未分类

至此,说明我们连接 MySQL 数据库 OK.

总结

在学习过程中,使用别人做好的 Dockerfile,虽可以直接拿来使用,但如果能自给自足,那最好不过了。

通过自建 docker 开发环境过程中,也能让自己学到更多。接下来还会不断完善,最小化满足开发需要。

代码已放在 github 上,欢迎参考和提出 issue:

github.com/fanly/larav…

iptables time 时间匹配规则

这两天受FortiGate启发,试了下iptables的时间控制规则,整理如下:

1、每天固定时间段匹配

iptables -I FORWARD -s 172.17.1.132 -d 192.168.1.119 -m time --timestart 09:40 --timestop 09:59 -j DROP

2、按周固定时间段匹配

iptables -I FORWARD -s 172.17.1.132 -d 192.168.1.119 -m time --timestart 09:40 --timestop 09:59 --weekdays Wed,Thu -j DROP

3、按固定日期匹配,注这里比较特殊,可以看见下面的时间是17点不是9点,是因为时区的原因,要差8小时。

iptables -I FORWARD -s 172.17.1.132 -d 192.168.1.119 -m time --datestart 2014-3-19T17:40:08 --datestop 2014-3-19T17:59:50 -j DROP

附上帮助说明:

time match options:
    --datestart time     Start and stop time, to be given in ISO 8601
    --datestop time      (YYYY[-MM[-DD[Thh[:mm[:ss]]]]])
    --timestart time     Start and stop daytime (hh:mm[:ss])
    --timestop time      (between 00:00:00 and 23:59:59)
[!] --monthdays value    List of days on which to match, separated by comma
                         (Possible days: 1 to 31; defaults to all)
[!] --weekdays value     List of weekdays on which to match, sep. by comma
                         (Possible days: Mon,Tue,Wed,Thu,Fri,Sat,Sun or 1 to 7
                         Defaults to all weekdays.)
    --localtz/--utc   

Docker部署Hadoop集群

一、主机规划

3台主机:1个master、2个slaver/worker
ip地址使用docker默认的分配地址:

master:
主机名: hadoop2、ip地址: 172.17.0.2

slaver1:
主机名: hadoop3、ip地址: 172.17.0.3
主机名: hadoop4、ip地址: 172.17.0.4

二、软件安装

1、在docker中安装centos镜像,并启动centos容器,安装ssh。–详见”docker上安装centos镜像”一文。
2、通过ssh连接到centos容器,安装jdk1.8、hadoop3.0
可以按照传统linux安装软件的方法,通过将jdk和hadoop的tar包上传到主机进行安装。

获取centos7镜像

$ docker pull centos

大概是70多M,使用阿里云等Docker加速器的话很快就能下载完,之后在镜像列表中就可以看到
查看镜像列表的命令:

$ docker images

安装SSH

以centos7镜像为基础,构建一个带有SSH功能的centos

$ vi Dockerfile

内容:

FROM centos
MAINTAINER [email protected]

RUN yum install -y openssh-server sudo
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
RUN yum  install -y openssh-clients

RUN echo "root:abc123" | chpasswd
RUN echo "root   ALL=(ALL)       ALL" >> /etc/sudoers
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key

RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

这段内容的大意是:以 centos 镜像为基础,安装SSH的相关包,设置了root用户的密码为 abc123,并启动SSH服务
执行构建镜像的命令,新镜像命名为 centos7-ssh

$ docker build -t="centos7-ssh" .

执行完成后,可以在镜像列表中看到

$ docker images

构建Hadoop镜像

上面是运行了3个centos容器,需要在每个容器中单独安装Hadoop环境,我们可以像构建SSH镜像一样,构建一个Hadoop镜像,然后运行3个Hadoop容器,这样就更简单了

$ vi Dockerfile

内容:

FROM centos7-ssh
ADD jdk-8u151-linux-x64.tar.gz /usr/local/
RUN mv /usr/local/jdk1.8.0_151 /usr/local/jdk1.8
ENV JAVA_HOME /usr/local/jdk1.8
ENV PATH $JAVA_HOME/bin:$PATH

ADD hadoop-3.1.0.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.1.0 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH

RUN yum install -y which sudo

这里是基于 centos7-ssh 这个镜像,把 JAVA 和 Hadoop 的环境都配置好了
前提:在Dockerfile所在目录下准备好 jdk-8u101-linux-x64.tar.gz 与 hadoop-2.7.3.tar.gz
执行构建命令,新镜像命名为 hadoop

$ docker build -t="hadoop" .

在/etc/hosts文件中添加3台主机的主机名和ip地址对应信息

172.17.0.2      hadoop2
172.17.0.3      hadoop3
172.17.0.4      hadoop4

在docker中直接修改/etc/hosts文件,在重启容器后会被重置、覆盖。因此需要通过容器启动脚本docker run的–add-host参数将主机和ip地址的对应关系传入,容器在启动后会写入hosts文件中。如:

docker run --name hadoop2--add-host hadoop2:172.17.0.2 --add-host hadoop3:172.17.0.3 --add-host hadoop4:172.17.0.4 hadoop
docker exec -it hadoop2 bash 
$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys

hadoop部署

1.在workers文件中定义工作节点
在hadoop根目录下的etc/hadoop目录下新建workers文件,并添加工作节点主机信息。
按照步骤一中的主机规划,工作节点主机为hadoop3和hadoop4两台主机。如:

[root@9e4ede92e7db ~]# cat /usr/local/hadoop/etc/hadoop/workers
hadoop3
hadoop4

2、修改配置文件信息

a、在hadoop-env.sh中,添加JAVA_HOME信息

[root@9e4ede92e7db ~]# cat /usr/local/hadoop/etc/hadoop/hadoop-env.sh |grep JAVA_HOME
#  JAVA_HOME=/usr/java/testing hdfs dfs -ls
# Technically, the only required environment variable is JAVA_HOME.
# export JAVA_HOME=
JAVA_HOME=/usr/local/jdk1.8

b、core-site.xml

configuration><property>
<name>fs.default.name</name>
<value>hdfs://hadoop2:9000</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
</configuration>

c、hdfs-site.xml

<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop2:9001</value>
<description># 通过web界面来查看HDFS状态 </description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/dfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
<description># 每个Block有2个备份</description>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
</configuration>

d、yarn-site.xml

<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>hadoop2:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>hadoop2:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>hadoop2:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>hadoop2:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>hadoop2:8088</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>1024</value>
</property>
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>1</value>
</property>
</configuration>

e、mapred-site.xml

<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop2:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop2:19888</value>
</property>
</configuration>

f、为防止进坑提前做好准备

vi start-dfs.sh vi stop-dfs.sh

HDFS_DATANODE_USER=root
#HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
HDFS_DATANODE_SECURE_USER=hdfs

vi start-yarn.sh vi stop-yarn.sh

YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root

注意:
以上步骤完成以后停止当前容器,并使用docker命令保持到一个新的镜像。使用新的镜像重新启动集群,这样集群每台机器都有相同的账户、配置和软件,无需再重新配置。如:

a、停止容器

docker stop hadoop2

b、保存镜像

docker commit hadoop2 hadoop_me:v1.0

测试
1、端口映射
集群启动后,需要通过web界面观察集群的运行情况,因此需要将容器的端口映射到宿主主机的端口上,可以通过docker run命令的-p选项完成。比如:
将yarn任务调度端口映射到宿主主机8088端口上:

docker run -it -p 8088:8088 hadoop_me:v1.0

2、从新镜像启动3个容器

docker run --name hadoop2 --add-host hadoop2:172.17.0.2 --add-host hadoop3:172.17.0.3 --add-host hadoop4:172.17.0.4 -d -p 5002:22 -p 9870:9870 -p 8088:8088 -p 19888:19888 
hadoop_me:v1.0

docker run --name hadoop3 --add-host hadoop2:172.17.0.2 --add-host hadoop3:172.17.0.3 --add-host hadoop4:172.17.0.4 -d -p 5003:22 hadoop_me:v1.0 

docker run --name hadoop4 --add-host hadoop2:172.17.0.2 --add-host hadoop3:172.17.0.3 --add-host hadoop4:172.17.0.4 -d -p 5004:22 hadoop_me:v1.0

3.格式化
进入到/usr/local/hadoop目录下
执行格式化命令

bin/hdfs namenode -format

修改hadoop2中hadoop的一个配置文件etc/hadoop/slaves
删除原来的所有内容,修改为如下

hadoop3
hadoop4

在hadoop2中执行命令

 scp  -rq /usr/local/hadoop   hadoop3:/usr/local
 scp  -rq /usr/local/hadoop   hadoop4:/usr/local

4.在master主机上执行start-all.sh脚本启动集群
5.通过web页面访问

未分类

未分类

未分类

Docker环境部署问题汇总

docker 相关命令:

  • docker ps: 查看当前运行的容器
  • docker ps -a : 查看所有的容器
  • docker start {容器id或name} 启动指定容器
  • docker stop {容器id或name} 停止指定容器
  • docker rm {容器id或name} 删除指定容器

具体docker相关使用指导参考:
http://kb.cnblogs.com/page/53…

运行docker容器,出现如下错误:

Cannot connect to the Docker daemon. Is the docker daemon running on this host?

解决方法参见下面链接:
http://blog.csdn.net/hejjiiee…

Ubutntu安装完Docker后,执行

$ sudo service docker start

提示

Failed to start docker.service: Unit docker.service is masked.

解决方案:

执行如下三条指令

$ systemctl unmask docker.service
$ systemctl unmask docker.socket
$ systemctl start docker.service
x Installing Docker: FAILED

-----------------------------------STDERR-----------------------------------
bash: line 4: docker: command not found

需要在服务器上先安装docker:

$ sudo apt-get install docker.io

普通用户不能执行docker命令:

修改 /etc/group

docker:xx:ubuntu

Centos 6.5 安装docker 问题:

  1. 安装教程参考: http://h2appy.blog.51cto.com/…
  2. 错误提示:
docker: relocation error: docker: symbol dm_task_get_info_with_deferred_remove, version Base not defined in file libdevmapper.so.1.02 with link time reference,

解决办法,执行:

$ yum upgrade device-mapper-libs

参考:http://blog.csdn.net/ownfire/…

docker 容器快照部署步骤:

1.将容器快照拷贝到本地
2.导入容器快照可以使用 docker import 从容器快照文件中再导入为镜像,例如

$ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0

3.根据导入的镜像创建容器(根据需求做必要的端口映射)

$ docker run -d --name shijiyu_live -p 80:80 -p 3306:3306 -p 6379:6379 -p 1935:1935 -p 8087:8087 -p 50001:22 xinjiguaike/lnmp-shijiyu:v3 /etc/rc.local
$ docker run -d --name centos_i386_auto --restart=always -p 3307:3307 -p 6680:6680 -p 6681:6681 -p 6680:6680/udp -p 6681:6681/udp -p 50003:22 shijiyu/centos_i386:v3 /etc/rc.local

关于docker 容器ssh连上就断开的问题:

Try to change

UsePAM yes

on

shell

UsePAM no

in /etc/ssh/sshd_config (for CentOS)

docker 容器目录结构:http://blog.csdn.net/wanglei_…

解决ssh登录后闲置时间过长而断开连接:

修改/etc/ssh/sshd_config配置文件,找到ClientAliveCountMax(单位为分钟)修改你想要的值,
执行

$ service sshd reload

ssh 密钥 无法用root用户登录:

将home/ubuntu/.ssh/authorized_keys 拷贝到 /root/.ssh 下

awk,分隔符编辑截取字符

输入字段分隔符:awk的内置变量FS中保存了输入字段分隔符的值。使用FS的默认值时,awk用空格或制表符来分隔字段,并且删除各字段前多余的空格或制表符。可以通过在BEGIN语句中或命令行上赋值来改变FS的值。接下来我们就要在命令行上给FS指定一个新的值。在命令行上改变FS的值需要使用-F选项,后面指定代表新分隔符的字符。

从命令行改变字段分隔符:范例中演示了如何使用-F选项在命令行中改变输入字段分隔符。

$ cat employees
Tom Jones:4424:5/12/66:543354
Mary Adams:5346:11/4/63:28765
Sally Chang:1654:7/22/54:650000
Billy Black:1683:9/23/44:336500
$ awk -F: '/Tom Jones/{print $1,$2}' employees
Tom Jones 4424

说明:-F选项用来在命令行重新设置输入字段分隔符的值。当冒号紧跟在-F选项的后面时,awk 就会在文件中查找冒号,用以分隔字段。

使用多个字段分隔符:你可以指定多个输入字段分隔符。如果有多个字符被用于字段分隔符FS,则FS对应是一个正则表达式字符串,并且被括在方括号中。下面的范例中,字段分隔符是空格、冒号或制表符。

$ awk -F'[ :t]' '{print $1,$2,$3}' employees
Tom Jones 4424
Mary Adams 5346
Sally Chang 1654
Billy Black 1683

说明:-F选项后面跟了一个位于方括号中的正则表达式,当遇到空格、冒号或制表符时,awk会把它当成字段分隔符。这个表达式两头加了引号,这样就不会被shell当成自己的元字符来解释(注意, shell使用方括号来进行文件名扩展)。

输出字段分隔符:默认的输出字段分隔符是单个空格,被保存于awk的内置变量OFS中。此前的所有例子中,我们都是用print语句把输出打印到屏幕上。因此,无论OFS如何设置,print语句中用于分隔字段的逗号,在输出时都被转换成OFS的值。如果用OFS的默认值,则$1和$2之间的逗号会被转换为单个空格,print函数打印这两个字段时会在它们之间加一个空格。

如果没有用逗号来分隔字段,则输出结果中的字段将堆在一起。另外,OFS的值可以改变。

参考资料:http://www.linuxawk.com/jiaocheng/116.html

如何在shell脚本文件中获取awk的值, 存于变量中?——来看看shell中eval的用法

遇到了, 折腾了一会儿, 所以记一下:

错误1:

#!/bin/bash
a="hello world"
b=$a | awk '{print $2}'
echo $b

错误2:

#!/bin/bash
a="hello world"
b=echo $a | awk '{print $2}'
echo $b

正确姿势:

#!/bin/bash
a="hello world"
b=$(echo $a | awk '{print $2}')
echo $b

其中$(xxx)表示执行xxx命令后的结果

如果要把多个值保存在多个变量中, 怎么搞起呢? 可以用eval, eval的作用是什么呢? 看个例子, 就明白了:

#!/bin/bash
hello=good
eval "hello=world"
echo $hello

结果是world, 实际上就是把”hello=world”中的内容理解为一个语句,而不是一个串。

来看看:

#!/bin/bash
a="hello world"
b=$(echo $a | awk '{printf("var1=%s; var2=%s;",$1,$2)}')
echo $b
echo ${var1}
echo ${var2}
eval $b
echo ${var1}
echo ${var2}

结果:

ubuntu@VM-0-15-ubuntu:~/taoge/shell$ ./a.sh 
var1=hello; var2=world;


hello
world

分析一下,$b的结果是var1=hello; var2=world;

此时, “var1=hello; var2=world;”仅仅是一个串, 而已, 而不是语句。 所以此时var1和var2都为空, 因为这两个变量根本就没有出现过。

利用eval, 可以让”var1=hello; var2=world; “变成语句, 所以var1此时的值就是hello, var2的值是world

当然, 也可以一步到位:

#!/bin/bash
a="hello world"
eval $(echo $a | awk '{printf("var1=%s; var2=%s;",$1,$2)}')
echo ${var1}
echo ${var2}

不多说。