2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

python @ kubernetesでtwitterbotを作ってみた

Last updated at Posted at 2018-09-23

前置き

先般の記事で紹介したようにRaspberryPIでkubernetesクラスタを構築したのでこれでせっかくだからなにがしかのアプリを動かしてみたいと思いました。

構築したてのkubernetesにとってはwebサーバー、webシステムの類を動かすにはingress Controllerをセットアップしたり、DNSのセットアップをしたりと素のままでは使いづらいのでリクエストを受けるものではなくて、リクエストを投げるものを作ろうと思いました。

そして思いついたのがtwitterbotでした。これでkubernetesのJob/CronJobを用いて定期もしくは不定期にpostしてやることができれば実現が可能なはず

構成

  1. twitterにpostするためのアプリ(pythonで作成)
  2. そのアプリを動かすためのdockerコンテナ
  3. dockerコンテナを利用したkubernetesリソースは以下を作成
    • Job
    • Secret
    • ConfigMap

1.pythonアプリ

初めてのpython。先月にあったjetbrainsの半額セールでとりあえずall products packを購入したので今まで書いたことのあるJavaやPHP以外で何かコード書いてみたいなあと思ってpythonで書いてみました。
取っ掛かりとしてwebでよく散見されるサンプルコード拝借して以下のようなコードを書いてみました。

main.py
import os
import twitter

auth = twitter.OAuth(consumer_key=os.environ['TWITTER_AUTH'],
                     consumer_secret=os.environ['TWITTER_CONSUMER_SECRET'],
                     token=os.environ['TWITTER_TOKEN'],
                     token_secret=os.environ['TWITTER_TOKEN_SECRET'])

t = twitter.Twitter(auth=auth)

status = os.environ['TWEET']
t.statuses.update(status=status)

たった数行のクラスすら使わないしょーもないコードです。
ただ唯一気にしたのは認証情報やツイート内容を環境変数化してコンテナ作成後にも可変にできるようにしたということぐらいでしょうか。一応12FactorAppの考えを用いたつもりです。

2.Dockerコンテナを用意する

これが意外に厄介でした。
なぜならraspberryPI(raspibian)は32bitモードで動作するOSで、そのせいか世間で公開されているpython用のコンテナをベースに作成しようとするとかなりの確率でstandard_init_linux.go:190: exec user process caused "exec format error"というようなエラーが出てしまいます。
なのでraspberryPI用に作られた(と、思われる)イメージをベースにして以下のようなDockerfileからイメージをビルドしました。

Dockerfile
FROM resin/raspberrypi3-python:3.6-slim

WORKDIR /usr/local/src/twitter
USER root
RUN chmod -R 777 ./
RUN apt-get update && apt-get install -y git
RUN pip install setuptools wheel && \
    pip install pipenv
RUN git clone <1で作成したコードのリポジトリ> ./
RUN pipenv install

RUN命令は1つにまとめてしまった方が良いのかもしれません(その方がイメージがコンパクトになるらしい・・・)
アプリの部分と分離させるために毎回最新のコードをcloneするようにします。必要に応じて--depth 1のオプションをつけるといいでしょう。

3.kubernetesのリソースを用意する

今回はさっと動作を確認するためにJobを用いました。
CronJobを使う場合でもスケジュールの設定が増えるだけで他は同じです。24h/365days稼働しているkubernetesクラスタがあるならCronJobの方がいいでしょう。
我が家では今の所そこまでkubernetesクラスタを活用しているわけではないので基本電源は切っています。

Jobの作成

以下のようなマニフェストファイルを作成してやります

job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: twitter-bot
spec:
  template:
    spec:
      containers:
      - name: twitter-bot
        image: <作成したdocker image>
        command:
          - sh
          - -c
          - pipenv run python <main.pyへのパス>
        envFrom:
        - secretRef:
            name: twitter-token
        - configMapRef:
            name: tweet
      restartPolicy: Never
  backoffLimit: 4

Jobを作成すると指定したimageでpodが作成されてそのpod上で指定したコマンドが実行されます。
podが作成されるのでdeploymentと同様にボリュームをマウントさせることも可能です。
なので、コード上で引用していた環境変数をsecret, configmapに定義し、それをマウントさせます。
ファイルそのままでマウントさせたい場合はvolumeMountsを使用しますが、環境変数として使用してやりたい場合はenvFromを使用します。
配列形式になっているのでサンプルのように幾つでもマウントさせることはできるのですが、キー名(フィールド名)の衝突が起きないように気をつけてください。不安な場合はprefixを用いると良いでしょう。

        - configMapRef:
            name: tweet
            prefix: PREFIX_

とするとtweetで定義している環境変数EXAMPLEPREFIX_EXAMPLEで呼べるようになります。

Secretの作成

SecretとConfigMapは基本的に使用方法は同じですが、Secretは設定後にkubectl describeなどで設定値が確認できなくなる点が異なります。
その性質ゆえにパスワード等の秘密情報はSecretに定義するのがセオリーかと思います。(趣味で作るようなアプリはそんなにこだわらなくても良さそうだけど)
twitterのデベロッパー向けページからappを作成して「Keys and tokens」必要なkey, tokenを取得して以下のようなマニフェストファイルを作成します。

secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: twitter-token
data:
  TWITTER_TOKEN_SECRET: <Access token secret>
  TWITTER_TOKEN: <Access token>
  TWITTER_CONSUMER_SECRET: <API secret key>
  TWITTER_AUTH: <API key>

注意点としてkubernetesのSecretに設定される値はbase64エンコードされていないといけないので例えばAccess token secretの値がhogeだとしたら以下のようにエンコードしてaG9nZQ==を設定してください。

$ echo -n "hoge" | base64
aG9nZQ==

ConfigMapの設定

SecretとConfigMapの違いは先ほど述べたとおりです。ここではツイートする内容をConfigMapに定義してやります。以下のようなファイルを作成するだけです。

configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: tweet
data:
  TWEET: "text of tweet"

Secretと異なり、値は平文のままでOKです。

デプロイ(Job)の実行

マニフェストファイルが全て同じディレクトリにあれば以下のコマンドを実行するだけです。

$ kubectl apply -f path/to/yamlfile 
job.batch/twitter-bot created
secret/twitter-token created
configmap/tweet created

作成される(た)podの様子をモニタリングします。-wオプションでリアルタイム監視できます。

$ kubectl get po -w
NAME                READY     STATUS              RESTARTS   AGE
twitter-bot-bmdq4   0/1       ContainerCreating   0          5s
twitter-bot-bmdq4   1/1       Running   0         1m
twitter-bot-bmdq4   0/1       Completed   0         1m

Completedになっているので無事Jobが実行されたことがわかります。
CronJobを使えば定期的にpostする、まさにbotが作成可能です。

twitterにも反映されています。
スクリーンショット 2018-09-23 12.06.53.png

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?