Foreverly

メモ帳

minikubeでWordPress環境を構築

こちらKubernetes ハンズオンをやりました。 適宜コマンドや説明を修正、補足した作業メモです。

ゴール

VirtualBox環境の1VM上にk8s環境をつくりwordpressを構築していきます。

事前知識

Pod

Podはk8sでアプリケーションを動かす最小単位のリソースです。 同じプロセス空間、ネットワーク、ストレージを共有する1つ以上のコンテナから構成されます。 Podは必ずNode上で実行されます。

Node

Nodeはk8sのワーカーマシンで、仮想マシンか物理マシンです。 今回はvirtualbox上にminikubeというNodeが作られることを確認できます。

k8s環境の準備

minikubeとkubectlをMacにインストールします

brew cask install minikube brew install kubectl

minikubeでローカルにk8s環境作成

minikube start でk8sv1.10.0のシングルクラスタが作成できました。

minikube start
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

minikube statusminikubecluster がRunningになっていることを確認

minikube status
minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.102

冒頭でもいいましたが、Nodeとしてminikubeが確認できます。

kubectl get nodes
NAME       STATUS    ROLES     AGE       VERSION
minikube   Ready     master    24s       v1.10.0

k8s上にWordpressを構築

k8s上にwordpressmysqlのコンテナを立ち上げていきます。 DockerStoreにあるものを使っていきます。

DBのパスワードの秘密情報をk8sに保存

k8sの昨日でSecretsというものがあります。 これは秘密情報を Secrets というデータベースで管理して、 パスワードなどを必要とする Pod のみに送ります。 Secrets の中身は Key-Value ペアのリストでパスワードを保存し、対象のpodに送ります。 今回は password.txt というファイルを作成し、 Secrets に登録します。

vim password.txt

kubectl ceate secret コマンドで登録

kubectl create secret generic mysql-pass --from-file=password.txt
secret "mysql-pass" created

kubectl get secrets コマンドで、Secretsの一覧を取得できます。

kubectl get secrets
NAME                  TYPE                                  DATA      AGE
default-token-g46vb   kubernetes.io/service-account-token   3         3h
mysql-pass            Opaque                                1         8s

MySQLを起動

MySQLのPodをつくりMySQLを起動させます。 以下の内容で ./manifests/mysql-pod.yaml を作成します。

apiVersion: v1
kind: Pod
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
    tier: mysql
spec:
  containers:
  - image: mysql:5.6
    name: mysql
    env:
      - name: MYSQL_ROOT_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysql-pass
            key: password.txt
    ports:
      - containerPort: 3306
        name: mysql
  • apiVersion
  • kind
    • リソースの種類
  • metadata
    • Podに設定するメタデータ
    • Podの名前とラベルを設定することで同じアプリケーションが動作するPodが複数存在するときに絞り込みを行うことが可能
  • spec
    • Podの仕様についての定義
    • 起動時に渡す環境変数や、公開するポートなどをここで設定
    • 環境変数として MYSQL_ROOT_PASSWORD を定義し、Secretsに登録したパスワードを参照させる

kubectl apply コマンドでPodを作成

kubectl apply -f ./manifests/mysql-pod.yaml
pod "wordpress-mysql" created

kubectl get pods コマンドで、mysqlが起動していることを確認

kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE
wordpress-mysql   0/1       Pending   0          1m

-l でラベルを使って絞り込みもできます。

kubectl get pods -l app=wordpress -l tier=mysql
NAME              READY     STATUS    RESTARTS   AGE
wordpress-mysql   0/1       Pending   0          59s

kubectl logs コマンドでMySQLのログも確認できます

kubectl logs wordpress-mysql | tail -n 5
2018-05-05 08:04:52 1 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory
.
2018-05-05 08:04:52 1 [Warning] 'proxies_priv' entry '@ root@wordpress-mysql' ignored in --skip-name-resolve mode.
2018-05-05 08:04:52 1 [Note] Event Scheduler: Loaded 0 events
2018-05-05 08:04:52 1 [Note] mysqld: ready for connections.
Version: '5.6.40'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

mysqld: ready for connections. と出力されていることを確認できます。

MySQLに接続

kubectl port-forward コマンドで、Podのポートをフォワードさせます。

kubectl port-forward wordpress-mysql 13306:3306
Forwarding from 127.0.0.1:13306 -> 3306
Forwarding from [::1]:13306 -> 3306

Handling connection for 13306
Handling connection for 13306
Handling connection for 13306

ポート 13306 をしていしてMySQLクライアントでMySQLに接続できることを確認できました。

mysql -s -uroot -p -h127.0.0.1 --port=13306
Enter password:
mysql> show databases;
Database
information_schema
mysql
performance_schema

DBのデータを永続的に保存させる

MySQLのデータはPod上にあるので、Podが消えたらDBのデータも消えてしまいます。 なのでDBのデータを PersistentVolume に保存するようにします。

kubernetesでPersistent Volumesを使ってみる

./manifests/mysql-volume.yaml でPersistentVolumeを定義します。 local-volume-1というPersistentVolumeを作成します。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-volume-1
  labels:
    type: local
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/data/lv-1
  persistentVolumeReclaimPolicy: Recycle

適用すると、PersistentVolumeが作成されます。

kubectl apply -f ./manifests/mysql-volume.yaml
persistentvolume "local-volume-1" created

PersistentVolume一覧からlocal-volume-1が作成されていることを確認できました。

kubectl get persistentvolume
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
local-volume-1   20Gi       RWO            Recycle          Available

次に、PodがPersistentVolumeを取得できるようにします。 PersistentVolumeClaim というリソースを使いますので ./manifests/mysql-persistent-volume-claim.yaml で定義します。 PV(PersistentVolume)からPodに紐付けるための領域がPVC(PersistentVolumeClaim)です。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-lv-claim
  labels:
    app: wordpress
    tier: mysql
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  • Access Modes
    • Claimsは特定のアクセスモードでストレージを要求するときにボリュームと同じ規則を使用します。
  • Resources
    • Claimsはポッドのように、特定の量のリソースを要求することができます。この場合、要求はストレージ用です。同じリソース・モデルがボリュームと要求の両方に適用されます。

適用してPVC(PersistentVolumeClaim)を作成します。 PVCをつくることでPodにストレージを追加することができます。

kubectl apply -f ./manifests/mysql-persistent-volume-claim.yaml
persistentvolumeclaim "mysql-lv-claim" created

それではmysql PodがPVを使うようにマウント設定を行います。Deploymentsにもしておきます。 Deployment については以下もこちらも確認しました。

Kubernetes Deploymentを理解する Kubernetes: Deployment の仕組み

DeploymentReplicaSet を生成・管理し、 ReplicaSetPod を生成・管理します。 Rolling Back やローリングアップデート、Scaling でセルフヒーリングといった仕組みを提供してくれます。

./manifests/mysql-deployment-with-volume.yaml で定義します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
    tier: mysql
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql-pass
                key: password.txt
        ports:
          - containerPort: 3306
            name: mysql
        volumeMounts:
          - name: mysql-local-storage
            mountPath: /var/lib/mysql
      volumes:
      - name: mysql-local-storage
        persistentVolumeClaim:
          claimName: mysql-lv-claim

kubectl apply して、mysql Deploymentを作成

kubectl apply -f  manifests/mysql-deployment-with-volume.yaml
deployment.apps "wordpress-mysql" created

Deploymentを作ったので、Deploymentによって作られたPodと、最初に作成したPodがいる状態です。 wordpress-mysql-7584cf4c49-xx9t4 がDeploymentによって作られたPodです。

kubectl get pod -l app=wordpress -l tier=mysql
NAME                               READY     STATUS    RESTARTS   AGE
wordpress-mysql                    1/1       Running   0          48m
wordpress-mysql-7584cf4c49-xx9t4   1/1       Running   0          14s

古いwordpress-mysql Podは消します。

kubectl delete pod wordpress-mysql
pod "wordpress-mysql" deleted

Deploymentが作ったPodを見ると、 ReplicaSet でPodが管理されており、 Volumesmysql-lv-claimが登録されているのがわかります。

kubectl describe pod wordpress-mysql-7584cf4c49-xx9t4
Name:           wordpress-mysql-7584cf4c49-xx9t4
(略)
Controlled By:  ReplicaSet/wordpress-mysql-7584cf4c49
(略)
Volumes:
  mysql-local-storage:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  mysql-lv-claim
    ReadOnly:   false
  default-token-cwnn6:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-cwnn6
    Optional:    false
(略)

WordPressの起動

次は ./manifests/wordpress-pod.yaml に定義し、WordPressのPodを作成します。

apiVersion: v1
kind: Pod
metadata:
  name: wordpress
  labels:
    app: wordpress
    tier: front-end
spec:
  containers:
  - image: wordpress
    name: wordpress
    env:
    - name: WORDPRESS_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-pass
          key: password.txt
    ports:
    - containerPort: 80
      name: wordpress

kubectl apply をします。

kubectl apply -f ./manifests/wordpress-pod.yaml
pod "wordpress" created

Podが立ち上がりませんでした。

kubectl get pods -l app=wordpress -l tier=front-end
NAME        READY     STATUS             RESTARTS   AGE
wordpress   0/1       CrashLoopBackOff   7          17m

ログを確認

WordPressMySQLの接続ができていなそう。

kubectl logs wordpress | tail -n 5
MySQL Connection Error: (2002) php_network_getaddresses: getaddrinfo failed: Name or service not known

Warning: mysqli::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known in Standard input code on line 22

Warning: mysqli::__construct(): (HY000/2002): php_network_getaddresses: getaddrinfo failed: Name or service not known in Standard input code on line 22

WordPressのPod定義で、MySQLのホストを指定していないからので、 環境変数WORDPRESS_DB_HOST として渡してあげましょう。

WordPressMySQLの接続

Service というリソースを作ります。 サービスの転送先のポッドのセットは、ラベルとセレクターによって判別されます。 Serviceのspecとしては、ポート情報とどのPodにつなぐかを決めるselectorとclusterIPです。

Services Kubernetes "サービス"の概要についての自習ノート

./manifests/mysql-service.yamlMySQLの接続情報を定義します。

apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
    tier: mysql
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None

今回はまずService wordpress-mysql という名前の新しいオブジェクトを作成しました。 このオブジェクトは、TCPポート 3306 をラベルのある任意のPod、ここでは wordpress で使用できるようにします。

wordpress-mysqlサービスを作成します。

kubectl apply -f manifests/mysql-service.yaml
service "wordpress-mysql" created

Service一覧で確認

kubectl get service -l app=wordpress -l tier=mysql
NAME              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
wordpress-mysql   ClusterIP   None         <none>        3306/TCP   8s

Serviceを作成したら、wordpress Podを一度消して、 DB接続できるwordpress Podを作り直します。

kubectl delete pod wordpress
pod "wordpress" deleted
kubectl get pods -l app=wordpress -l tier=frontend
No resources found.

mysqlのホストとしてmysql Serviceを使うように定義を追加します。 spec/containers/envに、WORDPRESS_DB_HOSTを追加して、値に、wordpress-mysql Serviceの3306を指定しています。 ./manifests/wordpress-pod-with-mysql-host.yaml という名前で以下のを記述します。

apiVersion: v1
kind: Pod
metadata:
  name: wordpress
  labels:
    app: wordpress
    tier: frontend
spec:
  containers:
  - image: wordpress
    name: wordpress
    env:
    - name: WORDPRESS_DB_HOST
      value: wordpress-mysql:3306
    - name: WORDPRESS_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-pass
          key: password.txt
    ports:
    - containerPort: 80
      name: wordpress

kubectl applyして、再度Podを作成。

kubectl apply -f ./manifests/wordpress-pod-with-mysql-host.yaml
pod "wordpress" created

ログをみてみます。 WordPressが無事起動されています。 wordpressからwordpress-mysqlに繋がりました。

kubectl logs wordpress | tail -n 5
Complete! WordPress has been successfully copied to /var/www/html
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppres
s this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Sat May 05 09:32:32.910938 2018] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.25 (Debian) PHP/7.2.5 configured -- resuming normal operations
[Sat May 05 09:32:32.911000 2018] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

しかし、k8sの外からwordpressに繋ぐことができないので、wordpress用のサービスも作ります。 mysqlとは違い、外部から接続したいので、typeとしてNodePortというものを選択します。 これは、PodのポートとNodeのポートを接続するものです。

./manifests/wordpress-service.yaml で以下のyamlを作成します。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: wordpress
    tier: frontend
  name: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30180
  selector:
    app: wordpress
    tier: frontend

kubectl apply コマンドで、wordpress Serviceを作成。 applyすればブラウザからアクセス可能になります。

kubectl apply -f ./manifests/wordpress-service.yaml
service "wordpress" created

Service一覧から確認

kubectl get service -l app=wordpress -l tier=frontend
NAME        TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
wordpress   NodePort   10.101.18.94   <none>        80:30180/TCP   9s

minikubeでは、以下のコマンドでブラウザで開くことができます。 Wordpressのセットアップ画面が表示されることができます。

minikube service wordpress
Opening kubernetes service default/wordpress in default browser...

セルフヒーリング

wordpressコンテナがクラッシュした時に繋がらなくなってしまいます。 対応したくないものです。運用はラクにしたいですね。 Podはコンテナとストレージボリュームの集合というだけで、自分自身を管理するということをしませんでした。 DeploymentのリソースをつかうことでPodの管理が可能になります。 DeploymentReplicaSet を生成・管理し、 ReplicaSetPod を生成・管理でしたね。

./manifests/wordpress-deployment.yaml という名前で、以下のyamlを作成。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
    tier: frontend
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql:3306
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password.txt
        ports:
        - containerPort: 80
          name: wordpress

applyしてDeploymentによって自動的にwodpress Podが作成されることが確認できます。 古いPod(wordpress)は削除します。

kubectl apply -f ./manifests/wordpress-deployment.yaml
deployment.apps "wordpress" created

kubectl get deployment コマンドで、wordpress Deploymentが作成されていることを確認

kubectl get deployment -l app=wordpress -l tier=frontend
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
wordpress   1         1         1            0           7s

Deployment によってPodが自動作成されていることを確認。 wordpressはPodとして作成したもので、wordpress-5644c5ff4-fgbgbは Deployment によって自動作成されたものです。 また、最初に作成したwordpress Podは消しておきましょう。

kubectl get pods -l app=wordpress -l tier=frontend
NAME                        READY     STATUS    RESTARTS   AGE
wordpress                   1/1       Running   0          8m
wordpress-5644c5ff4-fgbgb   1/1       Running   0          23s
kubectl delete po/wordpress
pod "wordpress" deleted

Deploymentは定義した状態を維持しようとします。 例えば、Podを削除しても新しいPodが自動的に作成され、Podが1台動いているという状態が維持されるます。

kubectl delete pod wordpress-5644c5ff4-fgbgb
pod "wordpress-5644c5ff4-fgbgb" deleted
kubectl get pods -l app=wordpress -l tier=frontend
NAME                        READY     STATUS        RESTARTS   AGE
wordpress-5644c5ff4-fgbgb   0/1       Terminating   0          54s
wordpress-5644c5ff4-w7h9z   1/1       Running       0          6s

このように wordpress-5644c5ff4-fgbgb が削除されると、 wordpress-5644c5ff4-w7h9z というPodがDeploymentにより作られます。

これはk8sの特徴で、状態を維持しようとする機能があります。 これにより、アプリケーションがクラッシュしたりしても自動的に復旧され、 サービスの運用の負担を下げることができます。

Deploymentを使うように変えてもPodは1つのままですがPodの数を変更することも可能です。 次は kubectl scale コマンドでレプリカ数を変更して、Podの数を変えてみましょう。

kubectl scale deployment wordpress --replicas 5
deployment.extensions "wordpress" scaled

kubectl get pods でPodが4台追加されていることが確認できました。

kubectl get pods -l app=wordpress -l tier=frontend

NAME                        READY     STATUS              RESTARTS   AGE
wordpress-5644c5ff4-9kt5l   0/1       ContainerCreating   0          12s
wordpress-5644c5ff4-kvb4q   1/1       Running             0          12s
wordpress-5644c5ff4-vhkhq   0/1       ContainerCreating   0          12s
wordpress-5644c5ff4-w7h9z   1/1       Running             0          33s
wordpress-5644c5ff4-zq6sz   0/1       ContainerCreating   0          12s

これで、スケールアウトできる、wordpress環境の完成です。

# KVM仮想化ホストサーバ間でのゲストサーバ移動

KVM仮想化環境でゲストイメージを別のホストサーバに移動させたので、 手順をまとめておきます。

ゲストサーバの起動状況確認

virsh list --all などで対象のゲストサーバが存在するか確認しましょう。 またイメージファイルや転送先のホストのディスク容量なども確認しておきましょう。 virsh nodeinfovirsh dominfo <ドメイン名> でCPUやメモリなどの割当状況も確認しておきます。

移動するゲストイメージの停止

移動するゲストイメージを停止します。

virsh dominfo <ドメイン名>
virsh shutdown <ドメイン名>
virsh destroy <ドメイン名> #shutdownで停止しなかったら  
virsh dominfo <ドメイン名>

ゲストイメージのファイルコピー

定義ファイルとimageファイルをコピーします。 rsyncは転送の効率化のために、暗号方式や転送速度制限を行っています。

virsh dumpxml <ドメイン名> > /tmp/定義ファイル名.xml
scp /tmp/定義ファイル名.xml user@対象サーバのIP:~/
rsync -avS --progress -e "ssh -c arcfour" --bwlimit=250000 /var/lib/libvirt/images/イメージファイル名.img user@対象サーバのIP:~/
ionice -c3 nice -n15 md5sum /var/lib/libvirt/images/イメージファイル名.img

転送したファイルのチェック

imageファイルのチェック

ionice -c3 nice -n15 md5sum /path/to/イメージファイル名.img

定義ファイルの配置

権限等は他と揃えておきましょう、

mv /path/to/定義ファイル名.xml /etc/libvirt/qemu/

ハードリンク作成

imageファイルが消失してもいいようにハードリンク作成しておきます。

ln /var/lib/libvirt/images/イメージファイル名.img /var/lib/libvirt/hardlink/イメージファイル名.img

ゲストサーバをlibvirt 管理下に登録、起動

定義ファイルを定義して、起動

virsh define /etc/libvirt/qemu/定義ファイル名.xml
virsh dominfo <ドメイン名>
virsh start <ドメイン名>

設定の削除

移設元の設定は不要なので削除します。

virsh undefine <ドメイン名>

JAPAN CONTAINER DAYS V18.04に行ってきた

https://medium.com/@yukotan/japan-container-days-v18-04-%E3%81%AE%E8%B3%87%E6%96%99-4f380fb7b696

サイバーエージェントにおけるプライベートコンテナ基盤AKEを支える技術

https://speakerdeck.com/masayaaoyama/saibaezientoniokerupuraibetokontenaji-pan-akewozhi-eruji-shu

アドテクで求められる性能要件

  • Low Latency
  • High Traffic
  • High Computing

環境

AKEとよばれるプライベート基盤(オンプレ)

AKEとは

コンテナが流行り始めた2016年ごろにスタート。 ソースを読んで理解を深め、2017年04月ごろにリリース。 2017年07付きにk8s1.7がプロダクションでサポート。 type loadbalanceをサポート。 プロダクション環境にAKEをリリース。 コンテナ環境に合わせたCICD環境を作り上げると効率が上がる。

コマンドでクラスタが作れる。 Heatとういう機能をつかって構築している。

一連の流れ

パッチを当てたK8sをbuildしOSimageをつくり、Opencluster Heatで自動構築して、E2E Testを実行する。 テストで使用しているもの https://github.com/heptio/sonobuoy

Key Features

  • K8sとSwarms support
  • openstackと統合
    • Heatで構築、CinderをPV、Designateで名前解決、Keystoneで認証する。
    • MagnumはL3ネットワークを使わなければいけないので、開発が遅い。細かい設定ができない。
    • Rancher 2.0はGAが5月だった。細かい設定ができない。
    • Tectonicは知名度が低くかった。細かい設定ができない。
  • L4/L7ロードバランサーを用意
    • NodePort + 手動LBだとノードのスケールしたり、LoadBalancerの操作が必要で大変。
    • type: LoadBalancerはCloud Provider Integrationで実装、OpenStackではOctaviaが使える。
    • Octaviaは性能不足なのでBaremetal LBと連携するようなCloudProviderを実装した。
    • ingressは面倒
  • monitoring log
    • addonを追加することで後から利便性を高めることができる。
    • addonとしてEFKstack、Datadog、helmなどがある。
  • Tuning
    • アドテクのシステムに合わせてチューニング
    • Network,Kernel,K8s,Hypervisor
  • Multi Countainer の実行サポート
    • k8sだけではなく、Docker Swamも対応

利点

自分たちでコンテナ基盤をつくれば、なんでも作れて触れて最高 ハイブリットクラウド構成 マルチコンテナランタイム対応

デメリット

実装コスト、運用コスト

マイクロサービスアプリケーションとしての機械学習

機械学習人工知能分野のブームがきている。 この分野では人材不足、獲得合戦だが、 今の学生は優秀なので数年後には解消されていそうとのこと。

機械学習をアプリケーションで利用する

処理時間、サーバコストも高い コードと学習モデルの整合性が難しい 学習環境の用意も必要 機械学習エンジニアの担当領域が不明 機械学習エンジニアはモデリングなどが得意だけど、システム設計とかAPI提供などはメインじゃない

コストの高い要求をした時のメルカリのSREチームの解凍

メルカリのSREチーム「Dockerfile用意してください。なんとかします」

はじめてのDockerfile

ビルド時にキャッシュがある。 キャッシュを意識した順序で書く。

一週間後、S3に画像が入っているので、GCPのk8sという構成。 Datadogでのモニタリング、Spinnakerでのデプロイリリース管理

http://techlife.cookpad.com/entry/2015/09/16/182917

はじめてのSpinnaker

GUIで操作できる。 自動deploy,immutableである。 http://tech.mercari.com/entry/2017/08/21/092743 http://tech.mercari.com/entry/2017/12/17/205719 http://tech.mercari.com/entry/2017/12/02/093000

1週間でできた理由は,モノリシックアーキテクチャからマイクロサービスに変わっていたことで,疎結合な作りになっていたから. これにとり,異なる機能を影響なく短期間でリリースできるようになった。 基本機能は Monolithic のまま、新機能や大幅な変更が伴う機能は Microservice可。

機械学習では汎用的につくるのは難しい。

キモになる機械学習の更新は,手動更新を都度SREに依頼していた.後から気づいたことだが, コードとモデルは密結合なため,整合性が保たれていないと動かない.複数のモデルをサポートし始めたら,自分の運用が破綻するのは目に見え始めていた。 マイクロサービスにしたメリットは機械学習モデルのサービスの組み込みが早い。 影響範囲が明確,改善の見込みがあれば早期のモデルデプロイ→気モデルの軽量化チューニングという投機的デプロイもできる。 機械学習エンジニアからすると,最大限の成果を上げるためにはモデリングへの注力が大事。 とはいえ、運用は無視できないので、モデリングと運用を分けたチームで運用する予定。 サービス関連系のオーバーヘッドも実は無視できない。

マイクロサービス化、依存パッケージとかを自由に使えるようになるのでいいけど、汎用イメージをつくるのはよくない。

PersistentVolumeでデータをBlueGreenデプロイする。

機械学習のモデルを頻繁に更新するのでコンテナーにしてマイクロサービスにすると相性がよい。

まとめ

機械学習エンジニアの立場からマイクロサービスは相性がいい。

  • 影響範囲がわかりやすい
  • アルゴリズム選択の自由度が高い
  • サービスの組み込みが早い

機械学習とMicroservicesとの親和性は高いがMicroservicesの雛形や指針があり、機械学習のシステムの専属のチームがあるとよい。

Yahoo!JapanのK8s as a Serviceで加速するアプリケーション開発

https://www.slideshare.net/techblogyahoo/yahoo-japan-kubernetesasaservice

Yahoo!ズバトクonk8s

サービス内容

くじが当たるキャンペーンプラットフォーム

技術スタックIaaS上のVMに社内独自パケージシステムとPHPから構成. キャンペーン中の数10倍に跳ね上がるトラフィックは,VMで捌くのが大変.CI/CD周りが自動化されていないので, リリースが遅い.パフォーマンステスト環境の整備が難しいなどの問題があった.

Yahoo ズバトクというサービスの基盤をkubernetesにした。 Zlabと協力してスタックをモダン化.OpenStackの上にk8s,Docker,ConcourseCIが,アプリもJavaで作り変えた

開発フローもモダン化

dev/stg/proの3環境にデプロイするまで,GitHubgのPR,Jenkins・独自ツールでビルド・構築していたのが、 GithubとConcurseが全てテスト/ビルド/デプロイが走る統合型に変わって便利になった。 リリースに掛かる時間も数時間から10分程度に変わった。

障害発生時の対応も変わった。 IaaSのHyperVisorが落ちたら、その上で動くVMを退避→サーバ稼働再開という流れ k8sを入れるとHyperVisorダウンをトリガにオートヒーリングで自動的にサービスが継続できる。 障害調査も分散環境のログ取得から,ログは1箇所で見れば良くなった。 今まではサーバーログを集めて調査してたが次はk8s側の機能でログを集約、splunkを使っている。

移行コストの話

内製プラットフォーム側の追加対応・CI/CD、言語のスイッチ、考え方や設計方針もk8s化する必要があった。 具体的にはクラウドネイティブ化。 これはZlabの協力を得て,考え方を変えた。 まだ移行の課題はあって。既存の設計をもう少しクラウドネイティブ化するための設計変更などもある。 今後はリリースまでの時間をもっと短くしたい。

Yahoo!JapanのK8s as a Service

Zlabは株式会社.ヤフージャパンの100%子会社.インフラ基盤技術の調査・研究開発。

Kaas

k8sクラスタの作成、削除、アップグレードを簡単値行える

  • セルフサービス
  • マネージド
  • スケーラブル

障害や問題のあるノードの修復(セルフヒーリング)

ノードAが壊れたら、削除して、新規のノードを自動作成し、クラスタを一定に保つ。

ゼロダウンタイムのアップグレード

利用可能なノード数を一定に保つことでサービス断なしに達成・ 全ノードの更新が必要な脆弱性対応にも即座に自動で対応できる。

クラスタアドオン

クラスタでサポートするアドオン:Ingres Controller、Ingressホストの自動登録。 Prometeus/Grafanaとダッシュボードで分かりやすく

Kaasの価値

煩雑なk8sのオペレーションから運用者を解放

  • クラスタの作成、削除、設定変更
  • ノード(VN)の追加、削除

これらは人間のやる仕事じゃないのでソフトウェア+Kaasにやらせる。 AUTOMATE ALL THE THINGS!!

KaaSの要件

数万台でも動くスケーラビリティ、非同期で処理できるモデル、処理が失敗しても再開できる・一部の破壊が全体の障害に影響を与えない堅牢性。

  • スケーラブル
  • 非同期モデル
  • 堅牢性
    • 処理が失敗しても再開できる

複雑な分散システムとして実装する必要があるが、近くに優れた分散システムの基盤があることに気づく。

KaaSは何を元に作っているのか.分散システム基盤としてのk8sに対して拡張機能を追加することで対応。 もともとのk8s自体が分散処理で動くように作り込まれているから k8sの拡張機能とすることで、付加価値が生まれる箇所のロジックに集中して開発ができている

分散システム基盤としてのk8s

kaas on k8s

母体のk8sで便利なもの.CustomResourceDeginitions。k8sAPIを拡張して,任意のリソースを追加できる。(エンドポイント,Watch APIなど) CRDを書いただけではなにもおきないのでコントローラを書く。 callbackとworkerを書けばOK。 カスタムコントローラの実装ができる。 これはControllerという形でフレームワークが用意されていて、実装者はコールバックだけをフレームワークに登録すれば良い。 カスタムリソースとカスタムコントローラのパターンで開発している

K8sのセキュリティのベストプラクティス

https://speakerdeck.com/ianlewis/kubernetesfalsesekiyuriteifalsebesutopurakuteisu

Ian Lwwis

k8sはインフラの提供をしてくれる

Guestbookアプリで説明 - WebFronted - web app - Message - メッセージを保存閲覧 - NGWord - NGワードを検出

k8s API

  1. Frontend Podからトークン取得
  2. トークン取得し、APIサーバを攻撃
  3. シークレットなどを取得し、さらにサービスを攻撃

Mitigate 1 & 2:RBAC

RBAC(Role Based Access Control)をきちんと設定しよう!

RBACは1.6から標準

Role Based Access Control ユーザやサーボすアカウントへロールを付与 ロールが権限を持つ get secrets tipdate configmap etc RBACはネームスペース展開 GKEではIAMと連携

Mitigate 2:API Sercer Firewall

API Server FirewallでAPIサーバーへのアクセスにIP制限かけよう!(Backend network側しかアクセスさせないようにする)

APIサーバへのアクセスをIPアドレスに制限 GKE なら1コマンドでできる

Mitigate 3:Network Policy

Network Policyで、DBやRedisなどKVSへのアクセスは必要なPodだけに制限しよう! telnet redis port番号 とかで接続できてしまう。 データベースへのアクセスを必要のあるPodに制限 ラブルセレクターでPodを洗濯 ネットワークプラグインで実装されている Calico, Weave,etc

ingressで設定したものしかportにアクセスできない。

ホストへアクセス

  1. コンテナ外へ突破
  2. kubeletを攻撃(権限や情報にアクセスされるなど)
  3. 同じホストに実行中のコンテナを攻撃

Mitigate1 :non-rootユーザで実行

コンテナをrootで実行すると色々できちゃうからroot意外のユーザーで実行する コンテナで別ユーザを実行すると、ホストのユーザがとれていない状態になる。 spec: securityContext: runAsUserでユーザを指定できる

runAsUser:1000

Mitigate1 :読み込みせんようファイルシステム

読み込み専用ファイルシステムもtrueにしておくと良い spec: securityContext: readOnlyRootFilesystem: true readOnlyRootFilesystem: true eadonlyfilesystemの使い所は大事

Mitigate1 :no_nre_privs

allowPrivilegeEscalation: false

自分が持っている権限委譲は付与できないようにする。 AllowPriviledgeEscalationはk8s 1.9での挙動では注意 https://qiita.com/inajob/items/943a634a1941030e5075

Mitigate 1: seccpmp/AppArmor/SELinux

seccomp + AppArmor + SELinuxで多段で守る eccomp + AppArmor/SELinuxで壁を増やす

SECCOMP

seccomp: security.alpha.kubernetes.io/pod: docker/default

metadata: annotations:seccomp.security.alpha.kubernetes.io/pod : docker/defaultとするとseccompが有効になってお勧め(ただしalpha)

seccompはv1.10でもまだalpha版 https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp

unshare -U でネームスペースから突破できてしまう。`

AppArmor

container .apparmor .security.beta.kubernates.io/hello: runtime/default

SELinux

SELinuxRedhat系、AppArmorはDebian系、

seLinuxはラベルで設定可能 https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Mitigate 2&3: kubeletの権限を制限する

RBAC for kubelet

--authorization-mode=RBAC,Node --admission-control=...,NodeReaatriction

Rotate lubelet certs

--rotate-certificates

Mitigate: PodSecurityPolicy

トラフィックを傍受

  1. ネットワーク上の通信を傍受

Istio

  1. サービス間のプロキシー
  2. 暗号化
  3. 証明証の自動更新
  4. ポリシーがセントラルサーバで集中して管理する

CNCF Cloud Native Interactive Landscape

https://landscape.cncf.io/

Cloud Native Apps 入門

https://speakerdeck.com/tnir/cloud-native-apps

What is Cloud Natic

クラウドネイティブなシステム

https://www.cncf.io/about/charter/

CNCF

2015年にk8sプロジェクトの寄贈先としてLinux Foudationのもとでスタート 20プロジェクト(2018年4月現在) メンバーシップ(スポンサー)~180社(2018/4) Technical Oversight Communite

What is Cloud Natic Application

cloud application maturity https://www.nirmata.com/2015/03/09/cloud-native-application-maturity-model/

CI/CD基盤

イメージビルドの省力化・自動化・標準化は重要 Gitlab Runner + Gitlab Container Registry

Gitlab CI評価

CNCF CIにも採用済 Cloud Native対応 GitHub/GHE対応 企業ユースには適する UIの洗練感はない

アーキテクチャ

積極的なマイクロサービスは行わない。 

マイクロサービス化に拘らない

  • 既存コード資産
  • 慣れたフレームワーク
  • I/Oを熟考した「サービス」を実装していく

KubeCon tips and k8s at Github

https://speakerdeck.com/tnir/kubecon-tips-and-kubernetes-at-github

The Twelve-Factor Appsに従う

コミュニティとの関わり

コミュニティに支えられた。

まとめ

k8sで実行できるようにアプリをcloud Native化しよう。k8sで廃れても対応できそう。 cloud Native化の仕組みが大事。 microservicesにこだわらないことも大事 コミュニティに支えられた。

Spinnakerを利用したk8sへの継続的デリバリ

k8sで安全にappをデプロイする仕組みについて ※安全とは作業ミスをなくすなど

導入するメリット

なぜコンテナを使うのか? コンテナを利用するメリットは ポータビリティ、軽量、実行環境の隔り

開発と本番環境の環境差分をなくす 設定漏れやパッケージの差分など

k8sの役割

複数のDockerホストの管理 コンテナの死活監視 障害時のセルフヒーリング ロードバランサーの組み込み

k8sにはCI/CDの機能がないので別途用意する必要がある

CI/CD

高品質なプロダクトを素早くユーザに届ける

CI:継続的インテグレーション DEVELOPE→DEPLOY→TESTを自動で回す仕組み a.g. Jenkins

CD:継続的デリバリ CIで回したものをstg,本番環境にデプロイする仕組み

Spinnakerにより、k8s上でCDを実現できる CIは別途用意

Spinnakerとは

Netflix社が開発したOSS マルチクラウド対応CDツール アプリケーションの自動デプロイに必要な機能が実装 パイプラインやNlue/Greenデプロイなど

機能紹介

k8sにデプロイする機能 GUIでパイプラインを作成できる パイプラインとはワークフローみたいなもの 複数のデプロイメント方法をサポート Red /Black Deploy(Blue/Green) Rollying Red/Black Deploy Canary Deploy

Red/Black Deploy

切り替え切り戻しを一瞬で行い時

Rollying Red/Black Deploy

断続的に切り替えたいとき

Canary Deploy

テスト的検査 最小構成だけ切り替えて様子見したいとき 問題なければ、切り替える

切り戻しもGUIやパイプラインで簡単に可能

パイプラインにカスタムスクリプトの実行が可能

serverspec,selemiumなどで工程ごとに試験ができる

CIツールは別途必要。 連携できるのは、TravisとJenkins

進捗状況を通知できる

パイプラインの成功、失敗をslackなどで通知など

パイプラインで承認フローを組み込める

stg,testは自動、本番は管理者の承認で先にすすめる。

承認(manual judgment)

その他機能

  • white-listed execution windows
  • chaos monkey integrarion
  • enable monitoring
    • datadog
    • prometheus
    • stackdrive
  • triggering on webhock
  • authentication

spinnaker と k8sのマッピング

instance, pod server group, replicaset clustrt, deployment load bakancers, service security group, Ingress

Spinnakerのこれから

2ヶ月ごとにバージョンアップ k8sのmanifestをデプロイ kayentaと連携

k8sの運用設計ガイド

細かい機能はあとで理解し、k8sはなにをするのかをまずは理解した方がいい。 明確な目的を持てば、自然とどう使えばいいかわかる。

テーマ

自律的なチームとシステムを作るためのk8sの利用/運用設計

why自律的?

独立的に動けて。自由がある。 moving fast, innovating

moving fast

速さというのは急ぐこと空ではなく、何かをなくすことから生まれる チューニングも思いクエリをなくす。承認リレーをなくす。

k8s自体の狙いとズレていないか?

3GB.4GBのイメージを使ってしまうとか k8s design architecture オーケストレーションを排除して、セルフオペレーションのためのもの。

チームの設計

技術と組織は表裏一体 どういうチームだったらk8sを使える?

コンウェイの法則を逆手に取る

自分が作りたいシステムを設計したチームをつくればいい

アプリケーション系、インフラ共通基盤系 これらは密結合せず、チームを分けた方がいい プロダクトチームとクラスタアドミンチーム

責任の設計

システムごとに必要なエンジニアリング作業がある

疎結合になる責任教会を決める

ソースコード、Container、ノード、クラスタ コンテナとノードが教会

プロダクトチームの責任

顧客の課題を解決

クラスタチームの責任

プロダクトチームのパフォーマンスを最大化すること。

You build it,you run it!!

クラスタの設計

開発環境、本番環境毎にクラスタをつくるのはよくない 環境が増えるたびにクラスタが増えて管理コストが上がる。 開発と本番環境が一致していることが保証しづらい。 ステージング環境が必要になっtラ、またクラスタをつくるのか。

リージョン毎に1つだけクラスタをつくる。

  1. 開発と本番環境が一致
  2. プロダクトがクラスタを意識しない

環境を特別視しない

開発と本番環境をわけても、serviceA がserviceBに影響を与えないようにしといけない結局、

リージョンごとに1つだけくらつたをつくる。

  1. aws,gcp,herokuに開発環境せんよう窓口はない
  2. ユーザが開発環境用として認識すればいい

プロダクト、サービス毎にクラスタをわける

メンテされないクラスタがでてくる。 他のアービスと熊津するばあいはどうする

クラスタ感通信yほり、暮らした無い通信のお方がネットワークの制御がしやすい。Neteork PolivyやIstopがあるので。

同じノードにのっているとセキュアじゃない

クラスタは1つ専用のノードを用意する

クラスタの粒度

Namespaceの設計

Namespaceでバーチャルクラスタを作る

環境毎にNamespaceを分ける

環境だけでなく差=ビス感もわけたい

サービス名+環境にNamespaceを分ける

Network Pokivyの設計

Namespaceレベルで制御する

基本はAll Denyにしてホワイト絵リストで通信可能なNamespaceを設計する

RBACの設計

RBCSCで権限委譲する admin Roleとcluster admin Roleでプロダクトチームと、クラスタアドミンチームでわける。

Borg-cluster adminチームはGmail adminチームの権限はみれない、 権限は強すぎるなら削った方外い。

アプリケーションContainerの設計

Disposable

  1. ステートレスに
  2. ログは標準出力に

k8sはあるべき状態に治す。いまの状態から。control move 死んでも立ち上がるので、大丈夫というアプリケーションをつくるのがよい。

IMuutable

  1. Latest tagは使わない
  2. 開発と本番環境で同じイメージを使う

Resilient

自然に復旧する動きにする

  1. Liveness Proveを使う(生きてるけど、バックエンドにつながらない時は通さない。Containerは生きているけど、プロセスがゾンビの時はkillしてもらう。)
  2. Crash only
  3. PDBを使う

Observable

  1. Liveness Prove,Readiness Probe
  2. ログは標準出力に
  3. メトリクス、トレース

Single Concern

  1. 1Container 1プロセス

Loosely COupled

!. Labelで引っ掛ける 2. 順番はないほうがいい 3. Affinityも極力避ける(疎結合にしたい) 4. (Externaml)Serviceで固定IPも避ける

12 Factoro Appをみるのがいい

オペレーションの設計

必ず宣言的なアプローチをロツ

  1. バージョン管理
  2. Control Loop
  3. 1リソース1ファイル

バージョン管理では GUIのデプロイツールはあんまりよくない。 yamlのパラメータを変えた時、どこ変えたのかわかんない どうあるべきかを書けばいい。

WHY k8sがYAMKベースなのか

YAMLCLIcurlrest APIが自然と使える。

モニタリングの設計

メトリクス イベント トレース どうはねているのか どのクエリ、どの関数がエラーなのか イベント、ログ なぜを把握するためのもの。 メトリクスやトレースにはきづけないもの 4つのレベルでモニタリングする ソースコード -> コンテナ -> ノード -> クラスタ

『コンテナ疲れ』と戦う、k8s - PaaS -ServerLessの活用法!

正しいテクノロジースタックの洗濯ができる知識

コンテナつらくないですか? コンテナ具術は抽象度が低い エンジニアのかばーしないといけない責任は似が広い k8sはエンジニアスキルが高いことを前提では SREも日本の企業にあっているだろうか

Containerの次はなんだろう

10年前はクラウド黎明期。 EC2のEUリージョン解説

5年前はクラウドは定着 DevOpsがもてはやされた。IaaSやCI/CDが中心。

テクノロジーの流れは 抽象度が高く、自動化の繰り返し 自動化の好循環

次はより抽象化、より自動化。 PaasやServerless

PaaS

開発者がアプリケーション開発に専念 アプリケーションのライフサイクルを支援するプラットフォーム PaaSの内部はContainerを使っている Containerが廃れてもPaaSは進化し続けている

Serverless

サーバ管理をせずともアプリケーションの構築と実行を行う仕組み

ServerlessとContainerの関係

Slervelessプラットフォームは込んでナでFucctionえお実行

CNCF serverless whitepaper http://gs2.hatenablog.com/entry/2018/02/16/114739

Fluentd and Distributed Logging in Container Era

ログにもプロダクションのログ。ビジネスや、サービスのためのログ。 サービスログ、システムログなどがある。 コンテナは生まれて消えるので、ログ管理は大変。マイクロサービスが流行り、いろんなコンテナに、アプリがある。

ソースレイヤーでパースする。先に統一すると後が楽。統一された型を持ったレイヤーにするのが大事。 Fluentdでは基本はjson型に変換する。 aggregatorはfluentdからfluentdに送ること。

logging driverはDockerコンテナのログを取れる。 fluent-loggerはfluentdはコンテナのアドレスを知らなくていい。

コネクションが増えるとパフォーマンスが落ちるので、コンテナのアプリケーションのログの送り先に直接redisに送るとかではなく、fuentdを送る。 バッファリングや、ロードバランシングを考えてくれる。分離して管理する。

agregation serverとしてfluentdをさらに置く。 コネクションを一つにまとめて、ロギングだけのコンテナを置くと、ソースサイドの負荷も下げられる。

destinationapiコールが多いか、少ないかで変わる。 Bigqueryとかは課金があるので、前段にアグリッションサーバを置くことがある。 ネットワークを分散して、障害で落ちてもいいように、ロードバランシングしたほうがいい。 ログは飛ばし先の分散が重要。

ログのフォーマットは統一しよう。アプリケーションレイヤーとシステムレイヤーが分断されるとツライ。 Fluentdで飛ばすログが1ファイルに全部入り(スタックトレースアクセスログなど)つらい。

macからvagrantへrake spec実行ユーザ変更

macのユーザでSSH接続しようとするので、vagrant ユーザに変えたかった。 documentには以下のように記載があった。

Serverspec with SSH backend logs in to target servers as a user configured in ~/.ssh/config or a current user. If you’d like to change the user, please edit the below line in spec/spec_helper.rb.

options[:user] ||= Etc.getlogin

~/.ssh/configssh_config に記載したがどうしても上の options[:user] ||= Etc.getlogin が先に読み込まれて 現在のログインユーザーで実行されてしまった。 なので以下のように強引に書き換えて通った。

-options[:user] ||= 'vagrant'
+options[:user] ||= Etc.getlogin

spec_helper.rb をいい感じに書き換えて ssh_config を読ませるようにしたい。

"msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).\r\n"の対応

環境

  • コントローラー:Mac
  • ターゲット:CentOS6.9(vagrant)

ansible -i inventory/inventory.ini playbook -m ping

pingで疎通確認をしたところ以下のメッセージが出た。 SSH接続失敗しているようだった。

"msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).\r\n"

公開鍵の権限など確認したけど問題なく原因がわからなかったのですが、 - vvv オプションで確認したところ以下のようにSSH接続するuserが指定されていないのが原因だった。

ESTABLISH SSH CONNECTION FOR USER: None

なので、 以下のようにインベントリにユーザを指定すれば解決しました。

192.168.33.27 ansible_user=vagrant

SSHが通らない時に原因はいくつかあると思いますが、 -vvv-vvvv を指定すれば原因が掴めそうです。

ReactでHello World!

Node.jsのインストール

Homebrewでインストール

brew -v
brew update
brew install nodejs
node -v

インストール用プロジェクトの作成

JSのプログラムをプロジェクト単位で管理。 npm init -y でパッケージの管理ファイル(package.json)を作成する。

mkdir hello_react
cd hello_react
npm init -y

package.jsonの変更

  1. desctiption(説明文)を記入
  2. Githubで公開しないprivateなプロジェクトと指定
  3. 開発ツールの起動スクリプトstartを定義
  4. webpack実行用スクリプトwebpackを定義
{
  "name": "hello_react",
  "version": "1.0.0",
  "description": "Hello React", #1
  "private": true,              #2
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server", #3
    "webpack": "webpack -d"        #4
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

npmパッケージをインストール

npm install react react-dom
npm install webpack webpack-cli webpack-dev-server --save-dev
npm install babel-cli babel-loader babel-preset-env babel-preset-react --save-dev
npm install eslint eslint-loader eslint-plugin-react --save-dev
npm install css-loader style-loader --save-dev

インストール結果の確認用Reackコード

  1. ディレクトリー作成
mkdir src
mkdir public
  1. .babelrc作成
vim .babelrc
cat .babelrc
{
  "presets": ["env", "react"]
}
  1. .eslintrc.json作成
vim .eslintrc.json
cat .eslintrc.json
{
  "env": {
    "browser": true,
    "es6": true
  },
  "parserOptions": {
    "sourceType": "module",
    "ecmaFeatures": {
      "experimentalObjectRestSpread": true,
      "jsx": true
    }
  },
  "extends": ["eslint:recommended", "plugin:react/recommended"],
  "plugins": ["react"],
  "rules": {
    "no-console": "off"
  }
}
  1. webpack.config.js作成
vim webpack.config.js
cat webpack.config.js
module.exports = {
  entry: {
    app: "./src/index.js"
  },
  output: {
    path: __dirname + '/public/js',
    filename: "[name].js"
  },
    devServer: {
    contentBase: __dirname + '/public',
    port: 8080,
    publicPath: '/js/'
  },
  devtool: "eval-source-map",
  mode: 'development',
  module: {
    rules: [{
      test: /\.js$/,
      enforce: "pre",
      exclude: /node_modules/,
      loader: "eslint-loader"
    }, {
      test: /\.css$/,
      loader: ["style-loader","css-loader"]
    }, {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
     }]
  }
};
  1. public/index.html作成
vim public/index.html
cat public/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1" />
  <title>React App</title>
</head>
<body>
  <div id="root"></div>
  <script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
  1. src/index.js
vim src/index.js
cat src/index.js
import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <h1>Hello, world!!</h1>,
  document.getElementById('root') 
)
  1. 確認
npm start

ターミナルに webpack: Compiled successfully. が表示されたら ブラウザーhttp://localhost:8080 をアクセスしてHello World! と表示されたらOK.

Pythonのクラスの基本

クラスの基本

クラスの書式

class クラス名:
    メソッドや属性

メソッド

クラス内の関数をメソッドと呼ぶ。 メソッドにはクラスに関連する処理を記述。

属性

クラス内のデータを属性と呼ぶ。 属性はクラスのインスタンスごとのデータを持つ。 self.hoge のようなクラスに関するデータのこと。

classのインスタンスの利用

クラスを設計図として、インスタンスを作成

c1 = NewClass()
c2 = NewClass()

右辺にクラス名()と書いてインスタンスを作成。 c1とc2がそれぞれインスタンスとなる。 作成時に値を渡したい場合は()の中に引数を渡せば良い。

initメソッド

__init__ メソッドはクラスからインスタンスが作られた直後に実行される特殊メソッド。 メソッドの書式は関数と同じ。 メソッドの第一引数にはインスタンス自身が渡される。(self)

class User(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def info(self):
        return self.name + ':' + str(self.age)

Userクラスのインスタンスを作る例。

user1 = User('田村ゆかり', 17)

インスタンス作成時にクラスタ名に渡される引数は__init__メソッドに渡されている。 クラスのメソッドの第一引数に指定されているselfは実際に呼び出し元から引数を設定する場合は無視する。 Userクラスの場合は、インスタンス作成時にnameとageに渡される値を設定する。