TypeScriptをはじめてみる
TypeScriptの雰囲気を掴むために、5分でできるチュートリアルをやってみる。
環境の準備
PC環境は汚したくないので、dockerで環境を作る。
#{APP_DIR}/docker-compose.yml
に以下を書く
version: '3' services: node: image: node volumes: - "./:/var/app" tty: true
コンテナを起動してログインする
docker-compose up docker-compose exec node /bin/bash
TypeScriptをインストール
cd /var/app npm install -g typescript
TypeScriptを書いていく
#{APP_DIR}/greeter.ts
を書いていく
// クラスの定義 class Student { // プロパティの宣言 fullName: string; // コンストラクタ // "引数名: 型" で引数の型指定ができる // 引数にpublicをつけることでプロパティとなる constructor(public firstName: string, public middleInitial: string, public lastName: string) { this.fullName = firstName + " " + middleInitial + " " + lastName; } } // インターフェースの定義 interface Person { firstName: string; lastName: string; } function greeter(person: Person) { return "Hello, " + person.firstName + " " + person.lastName; } // let user = { firstName: "Jane", lastName: "User"}; let user = new Student("Jone", "M.", "User"); document.body.innerHTML = greeter(user);
トランスパイルする
以下のコマンドでトランスパイルできる。 同じディレクトリにjsファイルができる。
tsc greeter.ts
参考:
Kubernetesの設定ファイルの書き方キホン
確認できる環境(minikube)の準備
$ brew install kubectl $ kubectl version --client $ brew install minikube $ minikube version
minikube コマンド
minikube start # 起動(デフォルトはDockerで起動) minikube status # 状態表示 minikube ssh # ホストOSにログイン minikube stop # 停止
※minikubeを起動すると、~/.kube/config
がよしなに変更されて、kubectlコマンドでminikube環境への接続が可能になる。
Pod
- 1個以上のコンテナの集まり
- 1Podに1コンテナ配置することが多い。
- 複数のコンテナでストレージを共有するようなケースでは1Podに複数コンテナを配置する
- Deploymentとセットで定義することが多いが、Pod単体を設定を書くこともできる。
- https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-overview/
Deployment
- Podをどこにいくつ配置するかを管理するもの
- PodはDeploymentと紐付けられてデプロイされる
- Deploymentの設定ファイルの中にPodの設定(Podテンプレート)を含む
- https://kubernetes.io/ja/docs/concepts/workloads/controllers/deployment/
Deploymentの設定ファイル
apiVersion: apps/v1 # 固定値 kind: Deployment # 固定値 metadata: name: nginx-deployment # Deployment名 labels: app: nginx # Podテンプレートと同じ値 spec: # レプリカ数 replicas: 3 # デプロイメントの履歴数 # デフォルト値は10 revisionHistoryLimit: 5 # このDeployamentが管理するPodをどう見つけるかの定義 # 基本はPodテンプレートの`labels`と同じにすれば良い selector: matchLabels: app: nginx # Podテンプレート template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 # コンテナが開けるポート
Deploymentの作成・確認・削除
$ kubectl apply -f nginx-deployment.yml # 設定をもとにオブジェクトを作成する $ kubectl get deployment # オブジェクトの一覧を表示する $ kubectl describe deployment nginx-deployment # オブジェクトの詳細情報を表示する $ kubectl delete -f nginx-deployment.yml # オブジェクトを削除する
Service
- Podにアクセスするためのゲートウェイ
- Pod自体は壊れたり作成される度にIPアドレスが変わるので、仲立してくれるService経由でアクセスする。
- https://kubernetes.io/ja/docs/concepts/services-networking/service/
Serviceの設定ファイル
kind: Service # 固定値 apiVersion: v1 # 固定値 metadata: # Serviceの名前 # 他のPodから `http://nginx-service` でアクセス可 name: nginx-service spec: # 接続タイプ # - ClusterIP クラスタ内部のみ接続可能(デフォルト値) # - NodePort クラスタ外から接続可能 type: NodePort # どのPodを対象にするか selector: app: nginx # 公開するポート ports: - name: http # 複数ポートを指定するときはname必須 protocol: TCP port: 80 # 受け口ポート targetPort: 80 # 転送先ポート - name: https protocol: TCP port: 443 # 受け口ポート targetPort: 443 # 転送先ポート
Serviceの作成・確認・削除
$ kubectl apply -f nginx-service.yml # 設定をもとにオブジェクトを作成する $ kubectl get service # オブジェクトの一覧を表示する $ kubectl describe service nginx-service # オブジェクトの詳細情報を表示する $ kubectl delete -f nginx-service.yml # オブジェクトを削除する
アクセスできるURLの確認
$ minikube service nginx-service --url http://192.168.64.2:32599
コンテナにログインする
以下のコマンドでPod一覧を表示する。
$ kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-5d59d67564-2gzp2 1/1 Running 2 2d1h nginx-deployment-5d59d67564-4mvjs 1/1 Running 2 2d1h nginx-deployment-5d59d67564-wlglr 1/1 Running 2 2d1h
で、NAME値を指定してkubecltコマンドを実行することで、sshログインができる。
kubectl exec --stdin -tty nginx-deployment-5d59d67564-2gzp2 -- /bin/bas
参考
シェルで古いファイルを一括で消す
バックアップスクリプトでよくやるのだけど、毎回書き方を忘れているのでメモ。
# -execオプションを使う版 # {} が対象のファイルパスに置換されて実行される。 # -mtime +3 => 最終更新日時が、過去〜4(3+1)日前のファイルを表示する find ${TARGET_DIR} -type f -mtime +3 -exec rm -f {}; # xargsを使う版 # こっちのほうが-execオプションより速い find ${TARGET_DIR} -type f -mtime +3 | xargs rm -f
バックアップ数の世代制限を超えたら消す場合はこんな
cd ${BACKUP_DIR}; REVISION_COUNT=`ls | wc -l`; if [ ${REVISION_COUNT} -gt 10 ]; then ls | head -1 | xargs -Rf rm fi
シェルスクリプトのアタマに添えるおまじない
シェルスクリプトを書くときに、アタマに添えるおまじないをメモ。
#!/bin/sh # set -e # スクリプトの実行中にエラー(exit 0以外)が発生すると、そこでスクリプトが終了させる。 # というかつけてないと、エラーしても次の処理に進むから怖い。 # # set -u # 未定義の変数を使用すると、そこでスクリプトが終了させる。 # # set -o pipefail # パイプの途中でエラーが起きた場合もエラーが発生させる。 set -euo pipefail # どのパスから実行しても、スクリプトのあるディレクトリにcdしてから実行する。 cd `dirname $0` # 以下、メイン処理を書く
参考
proxy先がTCPコネクションを切ったときブラウザには何が返るか
ブラウザ → proxy(nginx) → origin(apache)
の通信経路で、originがTCPコネクションを切った場合、proxyは50xを返す。proxy(nginx)にはこんなログが出る。
proxy_1 | 2021/07/01 13:15:38 [error] 25#25: *2 upstream prematurely closed connection while reading response header from upstream, client: 172.20.0.1, server: localhost, request: "GET /php/ HTTP/1.1", upstream: "http://172.20.0.2:80/", host: "localhost" proxy_1 | time:01/Jul/2021:13:15:38 +0000 remote_addr:172.20.0.1 host:localhost scheme:http req:GET /php/ HTTP/1.1 status:502 size:494 response_time:5.655referer:- agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 upstream_addr:172.20.0.2:80 upstream_cache_status:- upstream_response_time:5.656
ブラウザで、ERR_CONNECTION_CLOSEDが出る場合は、ブラウザとproxy間の通信が切れたもの。
MySQLのバッファプール使用状況を確認する
ダーティページの使用状況を確認したかったので。
mysql> SHOW GLOBAL STATUS LIKE 'InnoDB\_buffer\_pool%'; +-----------------------------------+---------------+ | Variable_name | Value | +-----------------------------------+---------------+ | Innodb_buffer_pool_pages_data | 464754 | # バッファプール内のデータ合計 | Innodb_buffer_pool_pages_dirty | 0 | # ダーティページ | Innodb_buffer_pool_pages_flushed | 51792309 | # ディスクフラッシュしたページ数 | Innodb_buffer_pool_pages_free | 0 | # バッファプールの空き | Innodb_buffer_pool_pages_misc | 59534 | | Innodb_buffer_pool_pages_total | 524288 | # バッファプール内のページ数 | Innodb_buffer_pool_read_ahead_rnd | 82900402 | | Innodb_buffer_pool_read_ahead_seq | 41051358 | | Innodb_buffer_pool_read_requests | 2642185748634 | # バッファプールから読んだページ数 | Innodb_buffer_pool_reads | 1272273714 | # ディスクからバッファプールにロードしたページ数 | Innodb_buffer_pool_wait_free | 0 | | Innodb_buffer_pool_write_requests | 320720943 | # バッファプールに書いたページ数 +-----------------------------------+---------------+ 12 rows in set (0.00 sec) mysql> SHOW GLOBAL STATUS LIKE 'Innodb\_pages%'; +----------------------+------------+ | Variable_name | Value | +----------------------+------------+ | Innodb_pages_created | 1073458 | # バッファプールに作成したページ数 | Innodb_pages_read | 6795625969 | | Innodb_pages_written | 51793282 | # ディスクフラッシュしたページ数 +----------------------+------------+ 3 rows in set (0.00 sec)
参考
nginxのproxy設定メモ
/etc/nginx/nginx.conf
# 略 http { # 略 # proxy_cache_path: キャッシュファイルの本体 # keys_zone: 1mは共有メモリのサイズ。1MiBあたり約8000個のキーを保持できる # max_size: 全キャッシュファイルのサイズ合計の上限 # inactive: 指定した期間内にアクセスされなかったキャッシュファイルは、その有効期間に関わらず削除される(デフォルトで10分) # proxy_temp_path: オリジンからの応答を一時的に保存するパス # 参考: https://qiita.com/aosho235/items/bb1276a8c43e41edfc6f proxy_cache_path /var/cache/nginx keys_zone=zone1:1m max_size=1g inactive=24h; proxy_temp_path /var/cache/nginx_tmp; include /etc/nginx/conf.d/*.conf; }
etc/nginx/conf.d/example.com.conf
# proxy先の設定 upstream my_app { # 送信先のサーバをクライアントIPから算出する ip_hash; # 送信先のサーバ情報 # weightが大きいほど送信頻度が高くなる server 192.168.101:80 weight=1; server 192.168.102:80 weight=1; } # HTTPの設定 # HTTPSにリダイレクトする server { listen 80 proxy_protocol; server_name www.example.com assets.example.com; return 301 https://$host$request_uri; } # HTTPS # proxyする server { listen 443 ssl http2 proxy_protocol; server_name www.example.com assets.example.com; # X-Forwarded-ForからproxyのIPアドレス(192.168.0.0/24)を削って # 一番右側のIPアドレスを、$remote_addr変数にセットする # 参考: https://christina04.hatenablog.com/entry/2016/10/25/190000 set_real_ip_from 192.168.0.0/24; real_ip_header X-Forwarded-For; # ELB+SSLの場合は、こうする # set_real_ip_from 192.168.0.0/24; # real_ip_header proxy_protocol; # ステータスコードが20x,30xの場合にレスポンスヘッダに含める # 参考: https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header add_header Front-End-Https on; # レスポンスヘッダに含まれるnginxのバージョンを消す server_tokens off; # リダイレクト時のサーバ名に何を使うか # on: server_nameディレクティブのサーバ名(デフォルト) # off: Hostヘッダの値 # 参考: https://heartbeats.jp/hbblog/2012/04/nginx04.html server_name_in_redirect off; # アップロードのサイズ制限 # 参考: https://qiita.com/notakaos/items/4816ad71b90a9967fa18 client_max_body_size 10M; # クライアントリクエストボディをファイルとして書き出すか # on: ファイル書き出す+消さない # clean: ファイル書き出す+消す # off: ファイルに書き出さない(デフォルト) # 参考: http://mogile.web.fc2.com/nginx/http/ngx_http_core_module.html#client_body_in_file_only client_body_in_file_only clean; keepalive_timeout 5; # 使用する証明書の指定 ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers AESGCM:HIGH:!aNULL:!MD5:!LOW:!SSLv2:!EXP:!eNULL; ssl_prefer_server_ciphers on; # プロキシ先に送信する際のヘッダ設定 proxy_set_header X-Real-IP $remote_addr; # クライアントのIPアドレス proxy_set_header X-Forwarded-Proto $scheme; # クライアントとサービスエンドポイントで使用したプロトコル proxy_set_header Host $http_host; # Hostヘッダ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # X-Forwarded-Forに自身のIPを足した値をセットする proxy_set_header Authorization $http_authorization; # デフォルトでproxyに通さないヘッダを通す設定 proxy_pass_header Accept; proxy_pass_header Server; # proxy先のタイムアウト設定 proxy_read_timeout 300; proxy_connect_timeout 300; proxy_send_timeout 300; # proxy先がリダイレクトを返したときに、nginxがリダイレクト先を書き換えるか # proxy_redirect http:// https://; # とすると、httpをhttpsに書き換えてくれる proxy_redirect off; # setで変数に値をセットできる set $do_not_cache 1; if ($uri ~* "\.(jpeg|gif|png|jpg|webp)") { set $do_not_cache 0; } if ($request_method != GET) { set $do_not_cache 1; } # ファイルをキャッシュから取得するか # 0: キャッシュ使う # 1: キャッシュから取得しない proxy_cache_bypass $do_not_cache; # proxy先が返すCache-Controlヘッダを無視する proxy_ignore_headers Cache-Control; proxy_cache zone1; # キャッシュに使うメモリ領域を指定。名前は任意の値を使用可。 proxy_cache_valid 200 3m; # status=200の場合は3分キャッシュを使う proxy_cache_key "$scheme://$host$request_uri$is_args$args"; # /* へのアクセスを my_app/* へプロキシする location / { proxy_pass https://my_app/; } # trailing slashあり # /info01/abc へのアクセスは、https://example.jp/abc へ転送される # 参考: https://blog.cosnomi.com/posts/674/ location /info/ { proxy_pass https://example.jp/ } # trailing slashなし # # /news/abc へのアクセスは、https://example.jp/news/abc へ転送される location /news/ { proxy_pass https://example.jp } location /blog/ { proxy_pass https://blog.example.com/; # proxy先が返したリダイレクト先を /blog/ に書き換える proxy_redirect https://blog.example.com /blog/; proxy_redirect http://blog.example.com /blog/; # proxy先が返したレスポンスの文字列を /blog に書き換える # sub_filter_once offにすることで、複数個の書き換えを行う sub_filter "https://blog.example.com" "/blog"; sub_filter "http://blog.example.com" "/blog"; sub_filter_once off; } }