Oracle Cloud Always Freeで作る 0円Kubernetesクラスタ

これは何?

Oracle社が発表したAlways FreeサービスでKubernetesクラスタを作成する方法を紹介します。

f:id:inajob:20191006162003p:plain

Oracle Cloud Free Tier | Oracle 日本

Oracle Cloud Free Tierはクレジットカードの登録さえすれば、無料でいくつかのリソースを利用することができます。

特に今回利用するFree Tierは

  • 2つのVM(1/8 CPU, 1GB Memory)
  • 10TB/monthの外部通信

です。

 

以前こういう記事を書きました。

inajob.hatenablog.jp

この記事でははVultrというVPSサービスを使い$10でKubernetesクラスタを作る方法を紹介したのですが、そのとき利用したVPSのスペックは 1CPU,1GB Memory のVM2台でした。

 

CPUこそ劣るものの、これでできるならOracle CloudののFreeTierでもKubernetesクラスタが作れるのでは?と考え挑戦してみました。

注意

この手順を使って作るクラスタはインターネットからアクセスできる状態になります。この手順通り実施したとしても様々な攻撃のリスクが存在しています。この手順を実行し起きたいかなる問題も筆者は責任を負えませんので、個人の責任で作業を行ってください。

また、これらの手順を実行した結果によってOracle Cloudへの課金が生じる可能性があります、こちらに関しても筆者は責任を負いません

FreeTierへの登録

ここは割愛します。クレジットカードの登録などが必要です。

また、ここで登録したリージョンが「ホームリージョン」となり、Free Tierで利用できるのはそのリージョンだけになるようです(お金を払えばそれとは関係なくどのリージョンでも利用できます。)

ここFreeTierが発表されてしばらくはJapanリージョンではVMが払い出せない状況にありましたが、ここ数日で払い出せるように回復しているように見えます。

 

追記:この記事を書いている2019/10/06現在、再び払い出せなくなりました。(この症状の時 VM作成時に Out of host capacity というエラーが出ます。)

VMの作成

f:id:inajob:20191006131954p:plain

インスタンス命名は何でもいいです、イメージソースはここではUbuntuの18.0.4にします。また、パブリックIPを割り当てるために「シェイプ、ネットワーク、ストレージオプションの表示」をクリックします。

f:id:inajob:20191006132111p:plain

そして”Assign in public IP address”を選択します。

さらにSSHキーを適切に設定して「作成」をクリックします。

VMが作成できると「パブリックIPアドレスが表示されます。このIPにsshすることで、作成したVMにログインできます。

 

同じ要領でWorkerのVMも作成しておきます。

このようにして作ったVM2台はちょうどAlways Free Tierの要件を満たしており、無料で利用することができます。

これから作るKubernetesクラスタ

f:id:inajob:20191006161646p:plain

master, workerのVMを作り、その2台でKubernetesクラスタを構築します。ingress-controllerをデプロイし、インターネットからそこを経由してクラスタ内のWebアプリケーションにアクセスできるようにします。(0円で)

Kubernetes Nodeの構築

次にKubernetesのNodeとして必要なパッケージのインストールです。これをざざっと実行することで

  • 最新のDockerパッケージのインストール
  • 最新のKubernetesパッケージのインストール
  • Kubernetesとしては非推奨ですが)Swapの有効化とKubeletの設定

が行えます。

apt-get update && apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

apt-get update
apt-get install -y docker-ce
apt-get install -y kubelet kubeadm kubectl

dd if=/dev/zero of=/swapfile count=2048 bs=1M
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile   none    swap    sw    0   0" >> /etc/fstab

sed -i 's/\/usr\/bin\/kubelet/\/usr\/bin\/kubelet --fail-swap-on=false --system-reserved=memory=100Mi /' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

systemctl daemon-reload
systemctl restart kubelet

ネットワークの設定(Oracle Cloud)

Kubernetesクラスタを構築する前にネットワークの設定をする必要があります。

必要なポートの設定はInstalling kubeadm - Kubernetesが参考になります。

要するにMasterはWorkerからの6443、MasterからすべてのNodeへの10250が疎通できれば良さそうです。

またこれから利用するオーバーレイネットワークのWeaveNetで利用する6783ポートも開ける必要があります。

 

「仮想クラウドネットワーク」から(おそらくmasterという名前(初めに作ったVMと同じ名前になる?)目的のネットワークを選択し、さらにその中にあるサブネットを選択します(おそらく1つしかないです)。さらに、その中のセキュリティリストを選択し、下記のように設定します。

 

上のほうのルールはもとからあるものです。

f:id:inajob:20191006133749p:plain

ネットワークの設定(iptables

Oracle Cloudの設定とは別に各ホストのiptablesも設定する必要があります。

master

iptablesの設定は既存の設定に依存します。ここまでセットアップしたVMでは例えば下記のようになっているはずです。

# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
2    ACCEPT     icmp --  anywhere             anywhere
3    ACCEPT     all  --  anywhere             anywhere
4    ACCEPT     udp  --  anywhere             anywhere             udp spt:ntp
5    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
6   REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

 行番号6のルールより前に通信を許可しないと、通信が捨てられてしまいます。

5行目のような(ここではSSHを許可している)ルールを追加していく必要があります。

iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 6443 -j ACCEPT
iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 6783 -j ACCEPT
iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 10250 -j ACCEPT

 こんな感じで設定します。

Masterの構築

# kubeadm init --ignore-preflight-errors=swap

swapが有効だとうまくセットアップできないので、あえて無視するように設定します。

コマンドがうまく実行できるとkubeadm joinのスニペットが表示されます。

Workerの構築

# kubeadm join <前手順で生成されるものをコピペ> --ignore-preflight-errors=swap

 Workerでは基本的にはスニペットを実行するだけですが、ここでもswapを無視して進めるようにします。

kubectlでのアクセス

kubeconfigをコピーしてきます。(セキュリティ上はあまりよくないですが・・)

# cp /etc/kubernetes/admin.conf /home/ubuntu/
# chmod 644 admin.conf

 以降は一般ユーザで作業できます

 

$ export KUBECONFIG=/home/ubuntu/admin.conf
$ kubectl get nodes

 node一覧が表示されれば成功です。

ネットワークアドオンのデプロイ

 Pod間の通信を可能にするためにネットワークアドオンであるWeave Netをデプロイします。

$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

 

Ingress Controllerのデプロイ

Webサービスを公開するためにIngress Controllerをデプロイします。

ここでは GitHub - zlabjp/nghttpx-ingress-lb: nghttpx ingress controller for Kubernetes を使うことにします。

 

まず該当するingressリソースがない場合に表示する404画面用のPodをデプロイします。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: default-http-backend
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: default-http-backend
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: default-http-backend
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: default-http-backend
        # Any image is permissible as long as:
        # 1. It serves a 404 page at /
        # 2. It serves 200 on a /healthz endpoint
        image: k8s.gcr.io/defaultbackend-amd64:1.5
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi

 

apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: kube-system
  labels:
    k8s-app: default-http-backend
spec:
  selector:
    k8s-app: default-http-backend
  ports:
  - name: 8080-8080
    port: 8080
    targetPort: 8080
    protocol: TCP

次にingress-controllerが利用するServiceAccountとその権限を設定します。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nghttpx-ingress-serviceaccount
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nghttpx-ingress-clusterrole
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
        - events
    verbs:
        - create
        - patch
  - apiGroups:
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: nghttpx-ingress-role
  namespace: kube-system
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get
      - create
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: nghttpx-ingress-role-nisa-binding
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nghttpx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nghttpx-ingress-serviceaccount
    namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nghttpx-ingress-clusterrole-nisa-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nghttpx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nghttpx-ingress-serviceaccount
    namespace: kube-system

 最後にingress-controllerをデプロイします。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nghttpx-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: nghttpx-ingress-lb
spec:
  selector:
    matchLabels:
      k8s-app: nghttpx-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: nghttpx-ingress-lb
        name: nghttpx-ingress-lb
    spec:
      serviceAccountName: nghttpx-ingress-serviceaccount
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      containers:
      - image: zlabjp/nghttpx-ingress-controller:latest
        name: nghttpx-ingress-lb
        imagePullPolicy: Always
        livenessProbe:
          httpGet:
            path: /healthz
            # when changing this port, also specify it using --healthz-port in nghttpx-ingress-controller args.
            port: 11249
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        # use downward API
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 443
          hostPort: 443
        args:
        - /nghttpx-ingress-controller
        - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
        - --healthz-port=11249
        - --logtostderr

 これで、このクラスタWebサービスをデプロイする準備が整いました。

追加のネットワーク設定

インターネットからの80番アクセスを許可するために追加でネットワークの設定が必要です。

 

f:id:inajob:20191006141934p:plain一番下にある80番ポートについてのルールを追加しました。

 

また、workerのiptablesも合わせて追加の設定が必要です。


iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT

 (INPUT 6の”6”はルールを見て適切な行番号を指定する必要があります。)

 

ここで、手元のPCからworkerのパブリックIPにアクセスをしてみると

f:id:inajob:20191006142222p:plain

このようにそっけない404ページが表示されるはずです。これはKubernetesクラスタ内のPodが返したものです。

Webアプリケーションのデプロイ

最後に、nginxをクラスタ上にデプロイして動作確認をしてみます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  ports:
    - port: 80
  selector:
    app: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: test-service
          servicePort: 80

 これをデプロイしたのちに、先ほどと同様にworkerのパブリックIPにアクセスすると

f:id:inajob:20191006142525p:plain

おめでとう!無事Kubernetesクラスタ上のアプリケーションにインターネットからアクセスできるようになりました。

まとめ

Oracle CloudのAlways Free Tierを使って、Master1台、Worker1台のKubernetesクラスタを作ることができました。

貧弱な構成ですが、無料の範囲内でインターネットからアクセスできるKubernetesクラスタを作れるのは面白いおもちゃになりそうと感じました。

また、Oracle Cloudは初めて使いましたが、普段使っているVPSと遜色なく利用することができ、特段詰まることもありませんでした。

 

2回目のRakuChord(らくこーど)通販、完売しました

このブログでもたまに触れている、僕の制作している電子楽器「RakuChord(らくこーど)」ですが、以前3月に通販してから、かれこれ半年たちました。そして満を持して9/4から第2回の通販を開始していました。

f:id:inajob:20190907174249p:plain

毎日ちょろちょろと売れていき本日9/7に完売しました

 

RakuChordがどんな楽器か?というのは下記の動画が参考になると思います。

さらに詳しい説明は公式ページ(RakuChord(らくこーど) - 楽にそれっぽい演奏ができる電子楽器)を見ていただくとして、本日のブログでは前回からの差分や、今後の展開について紹介しようと思います。

ここまでの歩み

実は開発はかなり昔から行っており2010年の記事があります。

このころはユニバーサル基板に100均のまな板をエンクロージャにしています。

その後、様々な形を検討しています。これは小型化したバージョン。

そしてこちらは長いバージョン

月日は流れ・・

基板を発注できるようになりました。

そして3Dプリンタでケースを作れるようになったことで夢の「キット化」が実現したわけです。

で、2019年3月に初めての通販を実施。

で、今回記念すべき2回目の通販を行ったという流れです。

前回からの差分

バージョン表記

今回からバージョンを数字で表記するようにしました。今回がv1.3ということにしました。今後も変更を加えていくたびにこのバージョンで区別できるようにするつもりです。

互換性

今回販売したものは2019/3に販売したものと構造はほぼ同じで、ソフトウェアについても互換性があります。ということで2019/3バージョンをお持ちの方は最新版のファームウェアに更新することで、RakuChord v1.3を体験することができます。(ソースコードはこちら https://github.com/inajob/rakuchord

前回のハードウェアバグ修正

以前販売時にこのブログでも紹介した(https://inajob.hatenablog.jp/entry/rakuchord-e-commerce)ハードウェアの問題点を修正しています。具体的にはOLEDから発生するノイズを低減するための電解コンデンサを追加しました。

また、前回アドホックに追加したプルアップ用の抵抗も、ちゃんと部品としてフットプリントを用意しました。

アンプの音量増加

LM386周りの回路を見直して、音量が少し大きくなるように回路を改良しました。

組み立てやすさのための修正

前回はスイッチとダイオードが非常に近くにあったため、はんだ付けが難しいところがありました。今回少しマージンを大きめにとったので、前回よりは作りやすくなったと思います。

前回(D19が近すぎる)→f:id:inajob:20190907173641p:plain

今回(程よくマージンがあります)→f:id:inajob:20190907173656p:plain

スイッチのフットプリント変更

メインスイッチのフットプリントを変更し、オムロンの12mmx12mmのスイッチなどが利用できるようになりました。実際はキットに同梱しているスイッチがマウントできれば、まぁそれで十分なのですが、手元ではいろいろなスイッチで試して遊んでいます。

基板の色

バージョンごとに色は変えていきたいなと思い、今回は黄色にしました。思ったより暗い色で、個人的には前回の白のほうが好みです。まぁケースに隠れてしまうのでいいのですが・・

LM386を二個入れた

前回なぜか検品したにもかかわらず、LM386というICが動かない症例が複数あったため、とりあえずキットにはLM386を2つ入れてあります。全く根本対策になっていませんが、ひとまずこれで様子を見ます。

f:id:inajob:20190907190449p:plain

今後の予定

今回も完売ということですが、そろそろ需要があるのか心配になってきました・・、しかし少なくとも次もアップデートしたいことがあるので、引き続き販売を予定しています。

 

「買いたい!」という方は 下記から「入荷お知らせメールを受け取る」をクリックしておいてほしいです。

自作電子楽器 RakuChord(らくこーど) v1.3 - inajobの作品販売 - BOOTH

 この設定は販売者は見ることができるため、今後のRakuChord開発の励みになります。

また「応援したい!」という方は「スキ!」を押していただけると、こちらも開発の励みになります。

追加予定の機能

ここに書いているのはあくまで「案」であり、次のバージョンにすべてが搭載されるわけではないことをご承知おきください。

  • ケースの外からもアクセスしやすい拡張端子(OPシリーズとのSyncや、MIDI出力、外部音源ICの接続、アナログコントローラの追加、などを想定)
  • SMD部品の利用と半完成キット化
  • より扱いやすい筐体

などなど、が今のところ考えている改良です。(SMD化は次のバージョンでは難しいか?・・)

他にもほしい機能があればぜひぜひコメントやTwitterhttps://twitter.com/ina_ani)で教えてください。

 おまけ

こんかいも部品を頑張って数えました。キットはこれがつらい・・

f:id:inajob:20190907190609p:plain

 

Maker Faire Tokyo 2019即日レビュー #MFTokyo2019

ここ数年は展示する側として参加することが多かったMaker Faire Tokyoですが、今年は個人で応募して落ちたので 普通にに参加者として楽しむことにしました。

 

f:id:inajob:20190803203355p:plain

スポンサー企業

f:id:inajob:20190803203426p:plain

感謝感謝。STEMとかそういう色合いを感じたりもしますね。

雑に面白かった作品を紹介

面白かった展示はざざっとTwitterに書いたのですが、明日行く人もいると思うので、改めてブログにも書いておこうと思います。

あくまで僕が目にとまったもの、特に今年初めて見たものを中心に写真を撮っています。(毎回おなじみですごい!みたいなものはTwitterとかでたくさん出回っているのでそっちを見てくださいw)

(ブース番号を写真と紐づけられておらず、、あとで追記するかもしれません。)

 

f:id:inajob:20190803203517p:plain

いわゆる パリピデストロイヤー。いろいろ展示してあったけど、幻らしいのでこちらを写真に収めました。

f:id:inajob:20190803203644p:plain

こちらはスタイロフォームを自由自在にカットできる装置。
キットでの販売も予定されているのだとか・・

f:id:inajob:20190803203741p:plain

上とやや似ていますが、発泡スチロールを切り抜く装置。
特徴的なのは左手のスキャン装置(?)で手書きのデータを読み取って、カットしてくれるというところ。PCレスで発泡スチロールのカットができるので子供でも操作できるのが売りなのだとか。

f:id:inajob:20190803203914p:plainf:id:inajob:20190803203937p:plain

こちらはアクリル板にレーザーカットしたマスキングテープを貼った作品。いい雰囲気でした。

f:id:inajob:20190803204116p:plain

こちらはOpenJSCADの開発者の方のブースのようでした。
http://knowhave.com/karakuriclub/ ここの方のようです。

OpenJSCADの新しいバージョンのデモなどをされていました。

f:id:inajob:20190803204432p:plain

こちらは目が見えない方向けの「点字タグ」を3Dプリンタで作っているという方のブース。OpenSCADでデータを公開しているようで、簡単にタグが作れるとのこと。

f:id:inajob:20190803204549p:plain

こちらはスポンサーブースで発見したKorgの新しいシンセガジェット!
Volcaシリーズ的なアレですが、キットとして販売するらしいです。(Volcaよりは安いのだとか・・)SDKなども公開されるようなので、自作楽器に組み込んだりと夢が広がります。

f:id:inajob:20190803213136p:plain

フルカラー3Dプリンタのサンプル。いまやこんなにきれいに出るんですね!

f:id:inajob:20190803213456p:plain

風の力で動くからくり人形(ペーパークラフト)、リズムを調整するための歯車みたいなものがついていてオルゴールみたいな感じだった。

f:id:inajob:20190803221819p:plain

ちょっと変わった動きをする歩行ロボット。この写真、人を乗せて歩いています。

f:id:inajob:20190803221920p:plain

なぞに2つのロボットが立っていました。制御難しそう。

f:id:inajob:20190803221959p:plain

完成度の高いアーケード筐体。

f:id:inajob:20190803222035p:plain

microbit用のレトロ音源ICボード。
ここの方、Orca-c専用のRaspberryPiボードも作っているようで、もしやと思って聞いてみると↓の記事を読んでみて、作ってみたとのこと。ブロガー冥利に尽きます。

inajob.hatenablog.jp

(そして基板1枚いただきました。ありがとうございます!)

f:id:inajob:20190803222258p:plain

こちらは楽器Slackの会で聞いていた「エアコンを楽器にした」やつです。なんとも不思議な演奏体験でした。

f:id:inajob:20190803222341p:plain

こちらは「ピンポン玉」を使ったドットマトリクス表示機。ドットが切り替わるときの音にまでこだわったとのこと。

f:id:inajob:20190803231219p:plain

今年もキーボード勢の人気は健在。

f:id:inajob:20190803231248p:plain

このラップトップ風IchigoJam機、閉じたらカバンみたいに持ち運べるんです。いいな!

f:id:inajob:20190803222433p:plain

木とLEDを組み合わせたこの展示もよい雰囲気で印象に残りました。

f:id:inajob:20190803222938p:plain

木といえばこちらの作品も雰囲気が良かったです。薄い木の板の裏にマトリクスLEDを置いているのかな?

f:id:inajob:20190803222503p:plain

イデア商品的なこれ。「本を読みかけの状態で立てることができる」というブックスタンドのようです。面白い。

f:id:inajob:20190803222546p:plain

展示物どれだろう・・と思っていたら、このだるまの目!!という驚きの作品。

f:id:inajob:20190803222649p:plain

こちらはからくり式の加算器。大学の授業で半加算器からやったなー と思い出しました。

f:id:inajob:20190803222745p:plain

こちらの球体のキーボード。無線式でこの台座から持ち上げることができるのですが、、打ちやすい・・! ということはなかったです。 脳トレ的な?

f:id:inajob:20190803222833p:plain

こんな見た目ですが、れっきとしたドラムマシン。左右でそれぞれパターンを作ることができ、真ん中のトグルスイッチでどちらを再生するか決めることができる。という意外と本格的な仕様。

最後に↓。これ、実はMaker Faire Kyotoで見逃して非常に悔しかった展示で、今回ついに見ることができました。この動き「高度に発達した技術は魔法と区別がつかない」という言葉通り、魔法のようだと感じました。

また制作記録の写真集のようなものも、見せていただき、苦労とこだわりを感じました。

また、制作者の方が、まるで人に接するように、このロボットの髪の毛を直したり、服を整えたりする様子にとても愛を感じました。

 写真が撮れてないけど印象的だったもの

 

 プレゼン

今回は完全に観客として参加だったので、プレゼンテーションもいくつか見ました。

 

 一つ目はこちら

f:id:inajob:20190803223446p:plain

 

 こちらの本の著者の方の講演でした。僕はこの本Amazonで予約していたので、どんな方が書かれているのかな?という興味でこの講演を聞きました。

結果この講演だけでも面白い話がたくさん出てきて、本を読むのが楽しみになりました。

 

 二つ目はこちら

f:id:inajob:20190803223646p:plain

毎回すごい数の「プロッタ」を展示していらっしゃる”いしかわきょーすけ”さんです。

f:id:inajob:20190803223659p:plain

これこれ。今年は右側の2色出せるやつとか、直動機構を説明するための真ん中のクリアファイルみたいなやつが新作・・かな? 

f:id:inajob:20190803223817p:plain

とにかく同じものを作り続ける、というところで、プロッタ、特に「直動機構」について、様々なノウハウがつめこまれた素晴らしいプレゼンでした(資料公開してほしい・・ 資料公開していただきました!ありがたい!)

speakerdeck.com

 

完全に蛇足ですが、小説「空の境界」で”起源”というワードが出てきますが

作品世界において、あらゆる存在が持つ、原初の始まりの際に与えられた方向づけ、または絶対命令。あらかじめ定められた物事の本質。無生・有生を問わず全ての物事は抗えない宿命として、それぞれ何らかの方向性を与えられて存在している。個々の人間もまた、知ろうが知るまいがこの方向性に従って人格を形成し、存在意義を持つ。

https://ja.wikipedia.org/wiki/%E7%A9%BA%E3%81%AE%E5%A2%83%E7%95%8C

まさに、このいしかわきょーすけさん ”直動機構”が起源なんだろうと思いました。
それくらいに”なにか”に突き動かされるようにプロッタづくりに情熱を注がれている姿がいつも印象的です。

 

三つ目はこちら

f:id:inajob:20190803224711p:plain

プログラムを見た時には全く気にも留めなかった発表なのですが、ブースでこんなデモを見て、ひとめぼれしました。

f:id:inajob:20190803224724p:plain

すごい完成度の手書き風プロッタです。
プレゼンを聞くと、どうやらこれ、ベンチャー企業で取り組んでいる事例のようで、実際に既にサービスとして提供しているものだそうで、道理で完成度が高いわけだと思いました。

私も昔プロッタを自作したことがあったので、”筆順データはどうしているのか?”などかなりマニアックな質問をしたりしました。

inajob.hatenablog.jp



最後がこちら

f:id:inajob:20190803224151p:plain

まぁこの業界では有名人 高須さんが自身で翻訳された「ハードウェアハッカー」という書籍についての話でした。

こちらのプレゼンは動画で公開されています。→ https://www.youtube.com/watch?v=NGmj49DtQRg

 

ハードウェアハッカー ~新しいモノをつくる破壊と創造の冒険

ハードウェアハッカー ~新しいモノをつくる破壊と創造の冒険

 

この本僕、読んでいたのですが、 結構長い本で、トピックも様々なので、改めて翻訳者の高須さんからの紹介を聞くことで、全体の構成というか、この本で著者が言いたかったことみたいなのがより詳しく理解できた気がしました。

これを踏まえてもう一度読み直してみようと思いました。

そして、それ以上に自分も同人ハードウェア活動をもっと進めたい!と思いました。(RakuChordの通販第二弾の準備も進めていますよ!)

inajob.github.io

 

てな感じで、どのプレゼンも非常に面白かったです。

おまけ: 趣味TECH祭り

 同東京ビッグサイト会議室で行われていた趣味TECH祭りもちらっと見てきました

f:id:inajob:20190803225138p:plain

本当に会議室で行われている!!

f:id:inajob:20190803225203p:plain

昨年のMaker Faire Tokyoで出会ってからやたらと良く出会う「黄色い坊主」のカワヅさん。工具箱も黄色い!!

f:id:inajob:20190803225310p:plain

元ロボット芸人の”高橋ちゃん”さんのインディーズゲーム機コレクション(?)
じつはこの方もいつぞやかのMaker Faire Tokyoで出会った仲です。(確かArduboyのブースに案内する。という劇的な?出会いでした。)

てな感じで、実はMaker Faire Tokyoを通じて界隈の有名人と結構知り合っているんだなーなんてことを裏番組である趣味TECH祭りで感じたりして、しみじみしていました。

戦利品

f:id:inajob:20190803225855p:plain

チラシ系はたくさんもらいすぎたので後で整理するとして、ステッカーなどはこんな感じ。
写真は撮っていないけどShigezoneさん(https://twitter.com/shigezoneakiba)とこにSexyCyborgさんがいて、JLCPCBのノベルティを配っていたのでいただきました。

あとはKLabの方のブースで「RaspberryPiでネットワークを遅延させるデバイス」の紹介を聞いたらそのデバイス用の拡張基盤をもらいました。(このデバイス実際に業務で使っているのだとか・・)


右上の歯車みたいなのは上に書いたOpenJSCADのブースの方からいただきました。
あと写真には写っていないけど

この基板もらっちゃいました。僕もOrca-cデバイス作ろうかなー

まとめ

Twitterとかを見ていると「あ、あれ見逃した!」みたいなのが大量にあるので、皆さんもこういうブログ記事書いて僕に教えてください!

まぁこんな感じで12時の開場から19時まで完全に「客」としてゆっくりMaker Faire Tokyoを見てきました。
何年に一度かはこういうのも良いな、と感じました。

そして人が作っているのを見ると自分も作りたい! と創作意欲がわいてきました。取り急ぎ今手元に部品がそろいつつあるRakuChordの通販の準備を始めようと思います。

f:id:inajob:20190803225807p:plain

(いい感じの夕焼けが撮れたのでこの写真で閉めます。)

ノートパソコンを新調した

背景

最近のメインPCはノートパソコンにしているのだが、どうも今までのものが性能が低くて使いにくい・・

ということで新しいものを探すことにした

パソコンで行う作業

行う作業によりパソコンの性能を選ぶ必要がある

今までのマシンで特に「性能が低いな」と感じたのはブラウジング、ビルド、Dockerを使った作業の3つです。

特に、最近Kubernetesがらみの検証を行うときに、ブラウザ+Dockerの組み合わせで作業することが多く、この際にメモリ不足となるのが非常にストレスでした。

今までのパソコンのスペック

f:id:inajob:20190728101307p:plain

LIFEBOOK P771/Cです。( https://www.fmworld.net/biz/fmv/lifebook/1107/p771c/

法人用のノートパソコンのようで、これの中古を買って使っていました。(確か2-3万くらい)

OSはWindows10 ProなのでHyper-Vなどが使えます。

メモリは標準から増やして8GBに増設しています。(メモリはいくらだったか忘れた)

CPUはCore i5-2520M(2.5GHz) 、いわゆるSandyBridge(第二世代Coreプロセッサー

ストレージはSSDに換装していました(これもいくらだったかな)

ディスプレイは12.1インチで軽量だったので持ち運ぶには非常に便利でした。

 

しかし、メモリ不足に陥ることが多かったので、メモリは8GB以上必要。ビルドも少し時間が気になることがあったので、CPUも早いといいな、という感じで新しいPCを探します。

メモリの最大搭載量

メモリが8GB越えのノートPCを探していたのですが、8GB越えということは16GBまたは32GBくらいが現実的な選択肢となってきます。

今回は、もうメモリに悩みたくない!という強い思いで32GBのマシンを探していました。

メモリ32GBというと、各社のラインナップのなかのミドル~ハイエンドクラスのマシンか、ゲーミング用PCが候補にあがりますが、結構高い(15万越えとか)

高いマシンはもちろんそれ相応のスペックなのですが、私の使い方だとその性能を必要としていない気がしていて、ちょっともったいない気がします。例えば高性能なGPUや、無駄にコアの多いCPUがあっても使いこなせる気がしません。

メモリを交換する前提で型落ち機種を探す

ということで、メモリは買った後交換する前提で、探すことにしました。

つまり、「すこし型落ちの32GBまでメモリを増やすことができるノートパソコン」にフォーカスしたわけです。

 

調べていくとDellや、Lenovoのマシンに条件を満たすものが多そう・かつ中古が市場に出回っていることに気づきました

Dellのマシンについて、最大搭載メモリー量は下記ページを参考にしました。

https://blog.takuros.net/entry/20120605/1338910909

 

Latitude 5580に決めた

f:id:inajob:20190728100941p:plain

https://japancatalog.dell.com/pd/latitude-5580-laptop.html

ということでいろいろ探し回った挙句Latitude 5580に決めました。まぁめぐり合わせと、調査の疲れの折り合うところがこれだったということで・・

  • Window 10 Pro
  • Intel Core i5-6200U(2.3GHz)
  • メモリ: 32GB(8GBから増設済み)
  • ディスプレイ15.6inch Full HD
  • 256GB SSD
  • VGA/HDMI

中古で6万くらいで購入してメモリが2万くらいだったから、占めて8万円くらい?

(↓ メモリさらに安くなってる・・今が買いですよ!)

しばらく使った感想

CPUは第2世代→第6世代までひとっとびしましたが、それにより何かがすごい快適になったという気はしませんでした。第6世代といっても末尾が「U」の低電力版だからかもしれませんが。唯一早くなったと感じたのはArduino向けプログラムのビルドかな?

 

つまり実は僕はそれほどCPUを利用する作業をしていない・・ということがわかりました。

 

メモリとストレージは劇的に良くなりました。以前だとタブをある程度開くとブラウザがクラッシュしたり、頻繁にswapが発生してフリーズみたいなことが起きていましたが、メモリが32GBあるおかげで、そのようなことは一切起きなくなりました。

普段のメモリ使用量を見ると大体16GB近辺まで使っているので、妥協してメモリを16GBにしていると、危なかったかもしれません。やはり32GBくらいが基本的人権のように思います。

大量にタブを開く+Dockerを実行 というのができるようになって、非常に作業がしやすくなりました。

 

VGAHDMIの両出力があるという点も、便利です。プレゼンを行う際などに、コンバータが不要ですし、Windows機のHDMIVGA接続はMacなどに比べて非常にタフです。(個人的な印象です)

 

悪くなった点は唯一1つ、「でかくて、重たい」ことです。まぁこれは仕方ないかな・・・32GBメモリが載せられて、12インチくらいのマシンがあればさらによかったかなと思うところです。

 

ともあれ、そんな感じで今回のノートパソコン新調は大成功だったのではないかと思っています。

 

まぁ変にケチらず、最高級マシンをバーンと買ってしまえば、このようなことをうじうじ考えなくてもよくなるようにも思うのですが、、それではなんかちょっともったいない・・ちゃんと必要なところにだけお金をかけたい・・ という謎のこだわりにより、今回のような選択をしました。

人によってこの辺の感性や、こだわりポイントは違うと思うので、ほかの人のPC選定基準も聞いてみたいと思いました。

Raspberry Pi ZeroでORCΛ環境の構築

ORCΛとは?

f:id:inajob:20190625172122p:plain
ORCAは前衛的なUIのライブプログラミング環境です。グリッド状のマップにアルファベットを並べてプログラムを記述します。主に音楽制作やVJなどで利用することを想定しているようで、OSCやMidiUDPを受信できるプログラムに対してメッセージを送ることができます。

ORCAでは一般的なプログラム言語と違い、処理が上から下へ進むのではなく、「Bang」と呼ばれるタイミング指示の信号により処理が進みます。

「Bang」を発生させるオペレータは複数用意することができるので、自然と並列処理を記述することになります。

 

プログラムは1文字単位のアルファベットで構成されているため、一見しても何かの暗号のようにしか見えません。(近いものとして、Roguelike RPGやBrainf*ckのような難解言語が挙げられます。)

ORCΛをRaspberry Pi Zeroで動かしたい!

ORCAは手軽なライブコーディング環境であるため、さっと持ち歩くことができると、思いついたときに作曲することができるのでは?と考えました。

そこで手元にあるRaspberry Pi ZeroでORCAを動かす方法を模索してみました。 

ORCΛのC言語版「Orca-c」

本家ORCAは「electron」を使って作られており、そこそこのマシンスペックを要求します。はじめはこれをそのままRaspberry Pi Zeroで動かそうとしていたのですが、そもそもelectronがARMのv6に対応しておらず、ビルドすることができませんでした。(またおそらくビルドできたとしても現実的な速度で動かすのは難しそうでした。)

 

そこでORCAの説明をもう一度読み返すと同一作者のC言語版のORCAであるOrca-cがあることに気づきました。

github.com

Orca-cはUIにelectronではなくncursesを利用しておりCUIのコンソールで動作するもので、説明書にもRaspberryでの実行方法が書かれているため、今回の用途にはぴったりだと感じました。

Orca-cのインストール

公式サイトに書いてある通りですが、、

sudo apt-get install git libncurses5-dev libncursesw5-dev libportmidi-dev
git clone https://github.com/hundredrabbits/Orca-c.git
cd Orca-c
./tool --portmidi build release orca             # Build

でビルドし、バイナリが生成されます

音源をどうするか?

ORCAは単なるシーケンサなので、音を鳴らすためには別のソフトウェアが必要です。

最も手軽に試せそうなのはORCA公式の音源であるPilot(https://github.com/hundredrabbits/pilot)ですが、これもORCA同様electronにより作られています(おそらくWebAudioを使っている)。そのためRaspberry Pi Zeroで動かすには厳しそうだと感じました。

 

Orcaが連携できるのはOSC,UDPMidiの3種類です。

Raspberry Pi Zeroでも利用できそうなものは、、と考えると以下の2つのソフトウェアが候補にあがりました。

 

一つ目は「Sonic Pi」です。 こちらもライブプログラミング環境で、ORCAとはライバルの位置づけですが、OSCを受信できるため、ORCAでシーケンスを作りSonic Piで鳴らすという使い方ができるようです。Sonic PiはRaspbianにも同梱されており、Raspberry Piでも動作しそうです。しかし、手元の環境では、どうもOpenGLのライブラリ周りのトラブルでうまく動かないため、別の選択肢を探しました。(しかしおそらくSonic Piも使えると思います。)

次に考えたのが「Timidity」です。これはソフトウェアMidi音源です。以前Raspberry Piで動作させたことがあったので、これを試してみることにしました。

Timidityのインストールと起動

sudo apt-get install timidity timidity-daemon freepats fluid-soundfont-gm fluid-soundfont-gs

でTimidityがインストールでき、デーモンが起動します。

ただ、手元の環境だとなぜかデーモンが起動に失敗していたので、普通にコマンドラインで起動するようにしました。

timidity -iA # これを実行して端末を放置する

 

 

Raspberry Pi Zeroにオーディオ端子をつける

Raspberry Pi ZeroはほかのRaspberry Pi 2や3とは違いオーディオ端子がありません。HDMI接続でスピーカ付きのディスプレイを使っている場合などは、それでも良いのでしょうが、今回はSPI接続のディプレイを利用しているため、それも使えません。

 

しかし、Raspberry Piの設定を変更することで、GPIOにオーディオ信号を流すことができます。

今回は液晶もGPIOで制御していたのですが、うまい具合に液晶の制御には使わないGPIOが開いていたのでそこをオーディオ信号を流すことにしました。

 

以下を/boot/config.txtに追記してリブートすることでGPIO18とGPIO13にオーディオ信号を流すことができました。(HDMI接続の場合はさらにraspi-configでオーディオ出力の設定が必要だと思います)

dtoverlay=pwm-2chan,pin=18,func=2,pin2=13,func2=4 

とりあえずジャンパケーブルを使って、雑にGPIO13とGNDを引き出して、イヤホンジャックにつなげました。本当はアンプとか通すべきなんでしょうが、まぁ音が鳴ったのでこれで良しとします。

f:id:inajob:20190625172251p:plain

構成図

今回の構成を図にするとこんな感じです。

f:id:inajob:20190625171604p:plain

f:id:inajob:20190625172645p:plain

TimitidyとORCAの連携

ORCA-cはMIDIの連携を前提に作られているようで、非常に簡単に連携することができました。

./build/release/orca --portmidi-list-devices     # Select Midi Device

 

を実行するとMIDIバイスの一覧が出てくるので、そこからTimidityのポートの番号を確認します。

その後、下記のように番号を指定するとORCAが起動します。(この場合は2)

./build/release/orca --portmidi-output-device 2  # Start

ORCAからMIDI信号を送る

ORCAの操作は初見では全く分からず苦労しました。

とりあえず、BANGを一定間隔で発生させ、それに合わせてMIDIのNoteを送信するとても簡単なプログラムを作って、動作を確認しました。

f:id:inajob:20190625183227p:plain

このプログラムの意味はこんな感じ。

f:id:inajob:20190625184301p:plain

デモ

演奏の様子です。といってもまだ全然わかっていないので乱数で曲のようなものを鳴らしているだけですが、、

 

まとめ

とりあえずRaspberry Pi ZeroにOrca-cをインストールしてTimidityを通して音を鳴らすことができました。

音色を切り替えたりパーカッションのようなものを鳴らす方法は実はまだよくわかっておらず、またOrca-cと本系ORCAの違いなどもあるようなので、まだまだ道のりは長そうです。

しかしRaspberry Pi ZeroでORCAを動かしてみて、なんともいえない「しっくりくる」感を感じました。ORCAのインターフェースは解像度が低くてもかなりの情報量を詰め込めるようになっていますし、フルキーボードが必要な操作体系は、スマートフォンでは再現できません。さらにORCAの独特の画面のかっこよさはRaspberry Piのような電子工作ガジェットとぴったりの相性です。

 

皆さんもRaspberry PiORCAを使ってポータブル作曲環境を作ってみませんか?

 

使ったもの一覧

 

 

Pocket OperatorのリズムをArduinoから制御する

これは何?

Pocket Operator(ポケットオペレーター)という音楽ガジェットをご存知でしょうか?

Teenage Engineering ポケットオペレーター 8bitシンセ PO-28 robot 【正規輸入品】

Teenage Engineering ポケットオペレーター 8bitシンセ PO-28 robot 【正規輸入品】

 

 電卓のようなボタンをポチポチ押すことで素敵なビートを奏でてくれるガジェットです。

 

このPocket Operator、他の音楽ガジェットと同期する機能があります。

同期機能

Pocket Operatorの裏側にはオーディオジャックが2つ搭載されています。

1つは出力用で、ヘッドホンやスピーカにつなげます。もう一つは入力用で、デフォルトの動作はミキサーのように振舞います。

 

この入力用のオーディオジャックは設定によって、同期信号を受け取るようにできます。そうすることで複数のPocket Operatorのリズムを同期させることができます。

 

f:id:inajob:20190518175318p:plain

(https://www.youtube.com/watch?v=IApamM65si4 より)

今回は、この同期機能をArduinoから利用する方法を紹介します。(この方法は場合によってはPocket Operatorを壊してしまうかもしれません。実験する際は自己責任でお願いします。)

マイコンなしで実験

Arduinoなしでも、同期機能を試すことができます。

pocket operators – frequently asked questions

このページに詳細が記載されていますが、同期信号は5V以内で入れてくれ、とのこと。

また、同期信号は基本的にはオーディオの左チャンネルから送り、右チャンネルはオーディオを流すこともできます。

 

これらの機能は切り替えることができます。モードはSY<数字>という表記で表されます。

  • SY0 入力はステレオで受け取り、ミックスした結果をステレオ出力
  • SY1 入力はステレオで受け取り、ミックス結果を右チャンネル、同期信号を左チャンネル
  • SY2 入力は同期信号、出力はステレオ出力
  • SY3 入力は同期信号、ミックス結果を右チャンネル、同期信号を左チャンネル
  • SY4 モノラル入力を右チャンネルで受け取り、左チャンネルは同期信号。ミックス結果をステレオ出力
  • SY5 モノラル入力を右チャンネルで受け取り、左チャンネルは同期信号。ミックス結果を右チャンネル、同期信号を左チャンネル

さて、今回はリズムを別で作成してPocket Operatorを同期させるので、SY2 - SY5のどれかを設定するのがよさそうです。

とりあえずSY4にします。切り替えるのは「bpm」を押しつつ、右ノブの下のボタンを押します。

そして次のような回路を用意します。

f:id:inajob:20190518135401p:plain

 何でも良いのですが5Vを作って、その信号をスイッチを押したときだけ左チャンネルに流すようにします。スイッチを押していないときはGNDレベルにしたいので、1KΩでプルダウンさせます。

この回路のオーディオジャックとPocket Operatorの入力側のオーディオジャックをケーブルで接続します。

 

すると、ボタンをカチカチすると、Pocket Operatorのリズムが進むようになります。

これで、手動でリズムを制御することができました。

 

 Arduinoから制御する

ここまでくればArduinoで実行するのも簡単です。DigirtalWriteでLow Highを繰り返すことで、Pocket Operatorのリズムを制御することができます。

 

f:id:inajob:20190518140113p:plain

#define LEFT_CH 5
#define LED 13

void setup() {
  pinMode(LEFT_CH, OUTPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  digitalWrite(LEFT_CH, HIGH);
  digitalWrite(LED, HIGH);
  delay(100);
  digitalWrite(LEFT_CH, LOW);
  digitalWrite(LED, LOW);
  delay(100);
}

こんなソースコードを書くことでArduinoのLEDの点滅に合わせてPocket Operatorのリズムをならすことができます。 

 

 

 さらに下記のようにすると8ステップごとにテンポを変更するというわけのわからないリズムを作ったりもできます。

#define LEFT_CH 5
#define LED 13

void setup() {
  Serial.begin(9600);
  pinMode(LEFT_CH, OUTPUT);
  pinMode(LED, OUTPUT);
}

int wait =150;
void loop() {
  for(int i = 0; i < 8; i ++){
  digitalWrite(LEFT_CH, HIGH);
  digitalWrite(LED, HIGH);
  delay(wait);
  digitalWrite(LEFT_CH, LOW);
  digitalWrite(LED, LOW);
  delay(wait);
  }

  wait = random(50, 400);
}

 まとめ

ArduinoなどのマイコンからPoecket Operatorのテンポを制御する方法を紹介しました。音楽系のガジェットを作っている方は、ぜひPocket Operatorとの同期機能を実装してみてください。

f:id:inajob:20190518174543p:plain

VPS上に作ったkubernetesクラスタをv1.13系からv1.14系にアップグレードする

はじめに

f:id:inajob:20190418200920p:plain

僕はVultrという海外VPSのマシンを2台借りて、すごくチープなKubernetesクラスタを構築しています。下記が少し古いですが、セットアップ方法です。

inajob.hatenablog.jp

 

で、記事にはしていなかったのですが、このクラスタ、アップグレードを重ねてv1.13.2の状態になっていました。

 

今回この記事では、v1.13.2から最新のv1.14.1にバージョンアップした方法を紹介しようと思います。

 

アップグレードの苦労

今までのバージョンでのアップグレードは、実は何度も失敗してきました。失敗というのはKubernetesクラスタを構成するコンポーネントが立ち上がらなくなってしまい、kubeadmによるupgradeができなくなってしまうことです。

そうなるとクラスタを1から作り直していたのですが、そうすると当然クラスタ内にデプロイしていたアプリケーションを再度デプロイしなおす必要があります。クラスタ内で動作しているアプリケーションのmanifestは手元にあるので、それほど苦労することもないのですが、、結構悔しいです。

 

注意:これは我が家のクラスタがmaster 1台という推奨とは違う構成になっているのが主な原因です。masterを3台などでHA構成することで、ローリングアップデートができるようになり、そうすればアップグレードももっと簡単にできます。(激安クラスタの運命ですね。。)

 

ということで、今回は慎重に作業しようと誓いながら作業を始めました。

 宣伝コーナー!!

僕がKubernetesクラスタを動かしているVultrという海外のVPSサービスです。下記リンクから申し込むと$50のクーポンがつくはずです。

前述の記事の方法でセットアップすれば実質無料でおよそ5か月Kubernetesクラスタを運用できます。

よく似たサービスにDigitalOceanがありますが、VultrはTokyoリージョンがあるという点が大きな違いとなっています。

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

www.vultr.com

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

参考

本家にかなり詳しいアップグレードマニュアルがあります。なので詳しい人はこれを見ればアップグレードできるはず・・です。

kubernetes.io

 素直に指示に従ってみる

 まずはmasterのアップグレードです

 # apt-get update
 # apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.14.1-00 && apt-mark hold kubeadm
 ...
 The following packages have unmet dependencies:
  kubelet : Depends: kubernetes-cni (= 0.6.0) but 0.7.5-00 is to be installed

あれ?

kubernetes-cniというものをバージョンアップしようとしたが、kubeletが期待しているものと違う。ということらしい。

以前のインストールでkubeletのバージョンはapt-markによって固定しているので、それが原因でしょう。

しかし、ここでkubeletの固定を解除して、一気にkubeadmとkubeletをアップグレードしてはいけません。毎回ここで間違えます。そうするとkubeadmがkubeletの新しい設定を作る前に新しいkubeletが起動してしまい、コンポーネントが正しく起動しなくなってしまうことが過去にありました。

(今回もダメなのかどうかは確かめていないのでわかりませんが・・)

 ひとまずmasterをv1.13.5にアップグレードする

とりあえず、今はv1.13.2ですが、これをいきなりv1.14.1にするのではなくv1.13.5というv1.13系の最新のパッチバージョンに上げたのちに、v1.14.1にする。という作戦でいくことにしました。

 

# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.13.5-00 && apt-mark hold kubeadm
 The following packages have unmet dependencies:
  kubelet : Depends: kubernetes-cni (= 0.6.0) but 0.7.5-00 is to be installed
 E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.

 

 え、これもできないのか・・

パッチバージョン間のバージョンアップ方法はドキュメントに明記していないが、このタイミングならkubeadmとkubeletを一気に上げても大丈夫では? と考え

# apt-mark unhold kubeadm kubelet && apt-get update && apt-get install -y kubeadm=1.13.5-00 kubelet=1.13.5-00 && apt-mark hold kubeadm kubelet
 

 を実行。無事 v1.13.5にアップグレードできた。

v1.13.5のkubeadmでクラスタ

# kubeadm upgrade plan
 [preflight] Running pre-flight checks.
 [upgrade] Making sure the cluster is healthy:
 [upgrade/config] Making sure the configuration is correct:
 [upgrade/config] Reading configuration from the cluster...
 [upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
 [upgrade] Fetching available versions to upgrade to
 [upgrade/versions] Cluster version: v1.13.2
 [upgrade/versions] kubeadm version: v1.13.5
 I0418 02:03:25.771423   15661 version.go:237] remote version is much newer: v1.14.1; falling back to: stable-1.13
 [upgrade/versions] Latest stable version: v1.13.5
 [upgrade/versions] Latest version in the v1.13 series: v1.13.5
 
 Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
 COMPONENT   CURRENT       AVAILABLE
 Kubelet     1 x v1.13.2   v1.13.5
             1 x v1.13.5   v1.13.5
 
 Upgrade to the latest version in the v1.13 series:
 
 COMPONENT            CURRENT   AVAILABLE
 API Server           v1.13.2   v1.13.5
 Controller Manager   v1.13.2   v1.13.5
 Scheduler            v1.13.2   v1.13.5
 Kube Proxy           v1.13.2   v1.13.5
 CoreDNS              1.2.6     1.2.6
 Etcd                 3.2.24    3.2.24
 
 You can now apply the upgrade by executing the following command:
 
         kubeadm upgrade apply v1.13.5
 
 _____________________________________________________________________

できそう!

ということでアップグレード

 # kubeadm upgrade apply v1.13.5 
 
 [upgrade/staticpods] Moved new manifest to "/etc/kubernetes/manifests/kube-apiserver.yaml" and backed up old manifest to "/etc/kubernetes/tmp/kubeadm-backup-manifests-2019-04-18-02-04-52/kube-apiserver.yaml"
 [upgrade/staticpods] Waiting for the kubelet to restart the component
 [upgrade/staticpods] This might take a minute or longer depending on the component/version gap (timeout 5m0s)
 Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
 Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
 Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
 Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
 Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
 [upgrade/apply] FATAL: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced

死んだ!!!

 

kubeletのログを見ると、このログを最後にkube-apiserverが起動していない、nodeのconditionが異常だったのかな?

Apr 18 02:09:59 kubernetes kubelet[15375]: W0418 02:09:59.079140   15375 eviction_manager.go:160] Failed to admit pod kube-apiserver-kubernetes_kube-system(1b4484ac0b54c491dc5cfe4d158f31c0) - node has conditions: [DiskPressure]

あきらめずにkubeletをrestartしてみる

# systemctl restart kubelet

無事kube-apiserverが復活 何だったんだ・・

# docker ps |grep apiserver
 1044739d1d01        177db4b8e93a                        "kube-apiserver --au…"   About a minute ago   Up About a minute                       k8s_kube-apiserver_kube-apiserver-kubernetes_kube-system_1b4484ac0b54c491dc5cfe4d158f31c0_0
 d0b403dc4ec2        k8s.gcr.io/pause:3.1                "/pause"                 About a minute ago   Up About a minute                       k8s_POD_kube-apiserver-kubernetes_kube-system_1b4484ac0b54c491dc5cfe4d158f31c0_0

もう一度アップグレードを実行してみる。

# kubeadm upgrade apply v1.13.5
 ...
 [upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.13.5". Enjoy!
 
 [upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.

今度はうまくいった!

$ kubectl get nodes
 NAME         STATUS    ROLES     AGE       VERSION
 kubernetes   Ready     master    129d      v1.13.5
 worker01     Ready     <none>    129d      v1.13.2

kubectlでも上がっていることが確認できた。

 

workerをv1.13.5にアップグレードする

workerも上げておく

# apt-mark unhold kubeadm kubelet && apt-get update && apt-get install -y kubeadm=1.13.5-00 kubelet=1.13.5-00 && apt-mark hold kubeadm kubelet

(kubeadmは上げておく必要があったかな?)

$ kubectl get nodes
 NAME         STATUS    ROLES     AGE       VERSION
 kubernetes   Ready     master    129d      v1.13.5
 worker01     Ready     <none>    129d      v1.13.5

 

masterをv1.14.1にアップグレードする

ここからはあっさりとアップグレードできました。

# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.14.1-00 && apt-mark hold kubeadm
 ...
 The following packages will be upgraded:
   kubeadm
 1 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.
 Need to get 8,150 kB of archives.
 After this operation, 3,171 kB of additional disk space will be used.
 Get:1 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 kubeadm amd64 1.14.1-00 [8,150 kB]
 Fetched 8,150 kB in 0s (9,463 kB/s)
 (Reading database ... 99264 files and directories currently installed.)
 Preparing to unpack .../kubeadm_1.14.1-00_amd64.deb ...
 Unpacking kubeadm (1.14.1-00) over (1.13.5-00) ...
 Setting up kubeadm (1.14.1-00) ...
 kubeadm set on hold.

 

# kubeadm upgrade plan
 ...
 Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
 COMPONENT   CURRENT       AVAILABLE
 Kubelet     2 x v1.13.5   v1.14.1
 
 Upgrade to the latest stable version:
 
 COMPONENT            CURRENT   AVAILABLE
 API Server           v1.13.5   v1.14.1
 Controller Manager   v1.13.5   v1.14.1
 Scheduler            v1.13.5   v1.14.1
 Kube Proxy           v1.13.5   v1.14.1
 CoreDNS              1.2.6     1.3.1
 Etcd                 3.2.24    3.3.10
 
 You can now apply the upgrade by executing the following command:
 
         kubeadm upgrade apply v1.14.1
 
 _____________________________________________________________________
 
 $ kubeadm upgrade apply v1.14.1
 ...
 [upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.14.1". Enjoy!
 
 [upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
 
 $ apt-mark unhold kubelet &&apt-get update && apt-get install -y kubelet=1.14.1-00 kubectl=1.14.1-00 && apt-mark hold kubelet
 ...
 # systemctl restart kubelet

 

$ kubectl get nodes
 NAME         STATUS    ROLES     AGE       VERSION
 kubernetes   Ready     master    129d      v1.14.1
 worker01     Ready     <none>    129d      v1.13.5

workerをv1.14.1にアップグレードする

こちらも簡単。少しマニュアルとは違う指定にしましたが、この辺はお好みで。

# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.14.1-00 && apt-mark hold kubeadm
 // どうせworkerが1つしかないからdrainは意図的に行わない
 
 # kubeadm upgrade node config --kubelet-version v1.14.1
 [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.14" ConfigMap in the kube-system namespace
 [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
 [upgrade] The configuration for this node was successfully updated!
 [upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.
 
 //まちがえてkubeletが上がらないようにholdしておく
 # apt-mark unhold kubelet && apt-get install -y kubelet=1.14.1-00 kubectl=1.14.1-00 && apt-mark hold kubelet
 # systemctl restart kubelet

 

すべてがv1.14.1になりました

$ kubectl get nodes
 NAME         STATUS    ROLES     AGE       VERSION
 kubernetes   Ready     master    129d      v1.14.1
 worker01     Ready     <none>    129d      v1.14.1

 

おまけ:metrics-serverの設定

metrics-serverを入れないとkubectl top node, kubectl top podが動作しません。

ということでこの機会にmetrics-serverも入れることにします。

といっても、下記のmanifestを使うだけです。

github.com

 

我が家の環境の場合は

        command:
          - /metrics-server
          - --kubelet-preferred-address-types=InternalIP
          - --kubelet-insecure-tls

と2つ引数を変更する必要がありました。

 

kubelet-preferred-address-typesはnodeの名前でDNS解決できない環境で設定する必要があります。

kubelet-insecure-tlsは手抜きでやっています。本当はちゃんとした証明書を使うようにすべきです。

 

そして無事にkubectl top nodesが実行できました。

$ kubectl top node
NAME         CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
kubernetes   154m         15%    646Mi           82%
worker01     338m         33%    611Mi           77%