check windows cpu resources

メモ

マシンが暴走気味になることがあり、原因追跡するためにLinuxなどでいうpsコマンド相当の内容をログ取りたいと思った。 ので、軽く調べたところ、以下のウェブサイトがヒットした。

Windows がなんか重いときにコマンドで調べる(WMIC PROCESS)

上記サイトが丁寧に解説してくれている。 その中から、今回は CPUの利用率でフィルタ あたりを参考にした。

コマンド例

1
WMIC PATH Win32_PerfFormattedData_PerfProc_Process WHERE "PercentUserTime > 1" GET Name,IDProcess,PercentUserTime,CommandLine /FORMAT:CSV

ユーザタイムが1%以上使われたものをリストしている。 もし行数制限したい場合は、 PowerShellでhead,tail相当の処理を行う あたりを参考にする。

コマンド例

1
(WMIC PATH Win32_PerfFormattedData_PerfProc_Process WHERE "PercentUserTime > 1" GET Name,IDProcess,PercentUserTime /FORMAT:CSV)[0..10]

上記では、コマンドの引数が分からない。 そこで、それを詳細に調べようとすると、 コマンドラインからプロセスを特定 を参考にするとよい。 おいおい、自動的に要素を結合できるようにしよう。

参考

共有

Open project of EDC Connector with Intellij

1. メモ

EDC Connector 公式GitHub のプロジェクトをIntellijで開くための手順メモ。 いろいろなやり方があるが一例として。

1.1. 準備

gitクローンしておく。 ここでは、gitプロトコルを用いているが環境に合わせて適宜変更してクローンする。

1
2
$ git clone git@github.com:eclipse-edc/Connector.git
$ cd Connector

なお、必要に応じて特定のタグをチェックアウトしてもよい。 ここでは、v0.2.0をチェックアウトした。

1
$ git checkout -b v0.2.0 refs/tags/v0.2.0

当該プロジェクトでは、ビルドツールにGradleを用いている。プロジェクトに gradlew も含まれている。 本環境では、以下のようにGradle8.0を利用した。

◇参考情報

1
2
3
4
5
6
7
$ cat gradle/wrapper/gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

◇参考情報おわり

さて、ビルドに利用するOpenJDKをインストールしておく。 ここでは17系を用いた。(もともと手元の環境にあった8系を用いようとしたら互換性エラーが生じたため、17系を用いることとした)

1
$ sudo apt install openjdk-17-jdk

なお、 Gradle Compatibility に互換性のあるGradleとJDKのバージョンが記載されているので参考にされたし。

この状態でIntellijを使わずにビルドするには、以下のように実行する。 ここでは念のために、コマンドでビルドできることを確かめるため、あらかじめ以下を実行しておいた。

1
$ ./gradlew clean build

特に問題なければ、success表示が出て終わるはず。

1.2. Intellijで開く

ひとまず、プロジェクトトップでInteliljを開く。

1
$ <Intellijのホームディレクトリ>/bin/idea.sh . &

なお、IntellijにGradle拡張機能がインストールされていなければ、インストールしておく。「Files」→「Settings」→「Plugins」→「Gradleで検索」。

また使用するJDKを先にインストールしたJDK17を用いるようにする。「Files」→「Project Structure」→「Project」を開く。 「SDK:」のところで先ほどインストールしたJDKを設定する。 「Language Lavel:」も合わせて変更しておく。

開いたら、右側の「Gradle」ペインを開き、設定ボタンを押して「Gradle settings ...」を選択する。

「Build and run」章のところは、「Gradle」が選択されていることを確認する。

「Gradle」章のところは、「Use Gradle from:」でgradle wrapperの情報を用いるようになっていること、「Gradle JVM」でProject JDKを用いるようになっていることを確認する。

特に問題なければ、 BUILD SUCCESSFUL となるはずである。

1.3. トラブルシュート

1.3.1. Intellijのメモリ不足

ビルド中にヒープが不足することがある。 その場合は、 Intellijのメモリを増やす設定 を参考に、ヒープサイズを増やす。

「Help」→「Memory Setting」を開き、「2024」(MB)あたりにしておく。

1.3.2. Gradleのメモリ不足

ビルド中にヒープが不足することがある。 プロジェクト内にある、 gradle.properties 内に以下を追記する。ここでは最大4GBとした。

◇diff

1
2
3
4
5
6
7
8
9
10
11
diff --git a/gradle.properties b/gradle.properties
index 376da414a..d8da811a9 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -7,3 +7,6 @@ edcGradlePluginsVersion=0.1.4-SNAPSHOT
metaModelVersion=0.1.4-SNAPSHOT
edcScmUrl=https://github.com/eclipse-edc/Connector.git
edcScmConnection=scm:git:git@github.com:eclipse-edc/Connector.git
+
+# Increase Gradle JVM Heap size
+org.gradle.jvmargs=-Xmx4096M

1.3.3. JDKバージョンの不一致

当初、環境にあったJDK8系を用いていたが、ビルド時に構文エラー(互換性のエラー)が生じたため、JDK17を用いるようにした。

1.3.4. Gradleで使うJDKの選択

環境によっては、独自の証明書などをJDKのcacertsに導入して用いているかもしれない。 その場合は、用いているGradle、JDKに注意が必要。

例えば、/etc/ssl/certs/java/cacertsに独自の証明書を追加し、それを各JDKで用いるようにすると良い。

1
2
3
4
5
6
7
cd /etc/ssl/certs/java
cp cacerts cacerts.org
keytool -import -alias CA -keystore cacerts -file ~/any.cer
# passwordはchnageit
cd ~/.jdks/jbr-xxxxxx/lib/security
mv cacerts cacerts.org
ln -s /etc/ssl/certs/java/cacerts cacerts

2. 参考

共有

GitHub Actions for Hexo with Pandoc

メモ

遅ればせながら(?)、Circle CIからGitHub ActionsにHexo使ったブログのビルド・公開を移行する、と思い立ち、 このブログ生成ではPandocなどを利用していることから、独自のコンテナ環境があるとよいかと思い、調査。 Pandocインストールを含むDockerfileを準備し利用することにした。

◆理由

  • Pandoc環境を含む、GitHub Actionがなさそうだった
  • デプロイまで含めたActionがほとんどだったが、ビルドとデプロイを分けたかった(デプロイ部分は他の取り組みと共通化したかった)

Docker コンテナのアクションを作成する を参考にアクションを作成し、登録する。 またHexo環境の作成については、 heowc/action-hexo が参考になった。

GitHub Actionで用いられるDockerfile等の作成

Docker コンテナのアクションを作成する を参考に以下のファイルを作成する。 なお、 dobachi/hexo-pandoc-action に該当するファイルを置いてある。

1
2
3
4
5
[dobachi@home HexoPandocDocker]$ ls -1
Dockerfile
README.md
action.yml
entrypoint.sh

Dockerfile

Dockerファイル内では依存するパッケージのインストール、Pandocのインストールを実施。 NPMの必要パッケージインストールは、entrypoint側で実施するため、ここでは不要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[dobachi@home HexoPandocDocker]$ cat Dockerfile
FROM ubuntu:20.04

# You may need to configure the time zone
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# Install minimal packages to prepare Hexo
RUN apt-get update && \
apt-get install -y git-core npm wget

# Install Pandoc using deb package
RUN wget https://github.com/jgm/pandoc/releases/download/2.18/pandoc-2.18-1-amd64.deb
RUN apt-get install -y ./pandoc-2.18-1-amd64.deb

# Copy script for GitHub Action
COPY entrypoint.sh /entrypoint.sh

# Configure entrypointo for GitHub Action
ENTRYPOINT ["/entrypoint.sh"]

action.yml

最低限の設定のみ使用。

1
2
3
4
5
6
7
[dobachi@home HexoPandocDocker]$ cat action.yml
# action.yml
name: 'Build Hexo with Pandoc'
description: 'build Hexo blog using Pandoc generator'
runs:
using: 'docker'
image: 'Dockerfile'

entrypoint.yml

npmパッケージの依存パッケージをインストールし、HTMLを生成する。

1
2
3
4
5
6
7
8
9
[dobachi@home HexoPandocDocker]$ cat entrypoint.sh
#!/bin/sh -l

# Instlal Hexo and dependencies.
npm install -g hexo-cli
npm install

# Build
hexo g

GitHub Actionの設定

パーソナルトークンの生成

予め、GitHubの設定からパーソナルトークンを生成しておく。後ほど使用する。

GitHub Actionを動かしたいレポジトリのAction用トークンを設定する。

ここでは PERSONAL_TOKEN という名前で設定した。 内容は、先に作っておいたもの。

ワークフローの設定ファイル作成

GitHub Actionを使ってビルドするHexoブログのレポジトリにて、 .github/workflows/gh-pages.yml を生成する。

ここではプライベートのレポジトリで作成したHexo原稿をビルドし、 パブリックなGitHub Pages用レポジトリにpushする例を示す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[dobachi@home memo-blog-text]$ cat .github/workflows/gh-pages.yml
name: GitHub Pages

on:
push:
branches:
- master # Set a branch name to trigger deployment
pull_request:

jobs:
deploy:
runs-on: ubuntu-20.04
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod

# Deploy hexo blog website.
- name: Generate
uses: dobachi/hexo-pandoc-action@v1.0.8

# Copy source to repository for convinience
- name: copy sources
run: |
sudo chown -R runner public
cp -r ./source ./public/source

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.ref == 'refs/heads/master' }}
with:
external_repository: dobachi/memo-blog
personal_token: ${{ secrets.PERSONAL_TOKEN }}
publish_dir: ./public

参考

共有

Nest VM on Hyper-V

メモ

Get-VM を利用して、VMの名称を確認する。

1
2
3
4
5
PS C:\Windows\system32> Get-VM   

(snip)

ubu18 Running 0 9344 24.00:30:35.9900000 正常稼働中 9.0

入れ子になった仮想化による仮想マシンでの Hyper-V の実行 の通り、VM 名称を指定しながら設定変更する。

1
PS C:\Windows\system32> Set-VMProcessor -VMName ubu18 -ExposeVirtualizationExtensions $true

参考

共有

Getting_started_CKAN

メモ

CKAN公式サイト によると、CKANはデータマネジメントシステムである。 CKAN公式サイト の内容をもとに進める。

このメモの時点では、CKAN 2.9.5を対象とする。

なお、公式ドキュメントによると CKAN is a tool for making open data websites. とされており、 あくまで「オープンデータ向け」であることが伺える。

ドキュメントより

特徴

CKANの特徴 の通り、以下のような特徴を有している。

  • CKAN APIを提供
  • バックエンドのデータストア(アドホックなデータ置き場)
    • データソースかデータがpullされ、ストアされる
    • Data Explorer拡張を利用することでデータのプレビューが可能になる
    • 検索、更新などをデータ全てをダウンロード・アップロードせずにできる ★要確認
    • DataPusher 機能と一緒に使われることが多い
      • データソースから表形式のデータを取得し、DataStore APIを用いてCKANにデータ登録する仕組み
  • 拡張機能
  • 地理空間機能
  • メタデータ
  • データ管理のためのUI
  • キーワード検索
  • テーマ設定
  • 可視化
  • フェデレーション
  • ファイルストア

データのモデル

Users, organizations and authorization に記載の通り、基本的にはOrganizationに紐づけてDatasetが登録される。 Datasetは任意のフォーマットでよい。CKANにアップロードしてもよいし、単純にURLを登録してもよい。 デフォルトの挙動では、登録されたDatasetはPrivate扱いになり、所有するOrganizationに所属するユーザのみ見られる。

Adding a new dataset にある通り、Datasetを登録できる。 なお、Licenseに並んでいる項目を見ると、やはりオープンデータとの相性がよさそう、と感じる。

DataStoreとDataPusher

DataStore Extension に記載の通り、 DataStore拡張機能を利用すると、Data Explorer拡張機能と併用することで自動的にプレビュー可能になる。 またDataStore APIを利用し、データ本体を丸ごとダウンロードすることなく、検索、フィルタ、更新できる。

自動的にデータを取り込むData Pusher拡張機能と併用されることが多い。

DataPusher の通り、データを取り出し自動的にCKANに登録できる。 ただし、注意書きにある通り、制約があるので注意。

Data Dictionary の通り、DataStoreのスキーマ情報はデータ辞書で管理できる。

Downloading Resources の通り、表形式のデータをCSVやエクセルで読み込める形式でダウンロードできる。

DataStore APIを利用すると、DataStoreリソースを検索したり、インクリメンタルにデータを追加できる。 バリデーションの機能もあるようだ。

APIについては、 API reference に記載されている。

DataStoreの拡張

Extending DataStore に記載の通り、独自のDataStoreを利用可能。 正確には、実装可能。

DatastoreBackend がベースクラスである。

バックグラウンドジョブ

Background jobs の通り、メインのアプリケーションをブロックせずに処理を実行できる。

Dockerで動作確認

セットアップ

Installing CKAN with Docker Compose を参考に、Docker Composeを利用して簡易的に動作確認する。 事前に、DockerとDocker Composeを導入しておくこと。

また、 オープンソースのデータ管理システム「CKAN」を試してみた が分かりやすかったのでおすすめ。

ソースコードをダウンロード。 ここではステーブルバージョンを利用することにした。

1
2
3
4
$ mkdir -p ~/Sources
$ cd ~/Sources
$ git clone https://github.com/ckan/ckan.git
$ git checkout -b ckan-2.9.5 tags/ckan-2.9.5

設定ファイルのコピー 適宜パスワードを変更するなど。 環境によっては、サイトURLを変更するのを忘れずに。

1
$ cp contrib/docker/.env.template contrib/docker/.env

ビルドと起動

1
2
$ cd contrib/docker
$ docker-compose up -d --build

後の作業のため、ストレージを変数化(しなくても、作業はできる。ボリュームのパスを覚えておけばよい) (公式サイト手順の「Convenience: paths to named volumes」に記載あり)

1
2
3
4
5
6
$ export VOL_CKAN_HOME=$(docker volume inspect docker_ckan_home | jq -r -c '.[] | .Mountpoint')
$ echo $VOL_CKAN_HOME
$ export VOL_CKAN_CONFIG=$(docker volume inspect docker_ckan_config | jq -r -c '.[] | .Mountpoint')
$ echo $VOL_CKAN_CONFIG
$ export VOL_CKAN_STORAGE=$(docker volume inspect docker_ckan_storage | jq -r -c '.[] | .Mountpoint')
$ echo $VOL_CKAN_STORAGE

Datastoreとdatapusherを機能させるため、いくつか設定する。 まずはデータベースの設定。

1
$ docker exec ckan /usr/local/bin/ckan -c /etc/ckan/production.ini datastore set-permissions | docker exec -i db psql -U ckan

プラグインなどの設定

1
$ sudo vim $VOL_CKAN_CONFIG/production.ini

なお変更点は以下の通り。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$ sudo diff -u $VOL_CKAN_CONFIG/production.ini{.org,}
--- /var/lib/docker/volumes/docker_ckan_config/_data/production.ini.org 2022-01-22 22:22:11.992878002 +0900
+++ /var/lib/docker/volumes/docker_ckan_config/_data/production.ini 2022-01-22 22:23:56.367637134 +0900
@@ -21,7 +21,7 @@
use = egg:ckan

## Development settings
-ckan.devserver.host = localhost
+ckan.devserver.host = ubu18
ckan.devserver.port = 5000

@@ -47,10 +47,10 @@ [2/7337] # who.timeout = 86400

## Database Settings
-sqlalchemy.url = postgresql://ckan_default:pass@localhost/ckan_default
+sqlalchemy.url = postgresql://ckan_default:pass@ubu18/ckan_default

-#ckan.datastore.write_url = postgresql://ckan_default:pass@localhost/datastore_default
-#ckan.datastore.read_url = postgresql://datastore_default:pass@localhost/datastore_default
+ckan.datastore.write_url = postgresql://ckan_default:pass@ubu18/datastore_default
+ckan.datastore.read_url = postgresql://datastore_default:pass@ubu18/datastore_default

# PostgreSQL' full-text search parameters
ckan.datastore.default_fts_lang = english
@@ -101,7 +101,7 @@
## Redis Settings

# URL to your Redis instance, including the database to be used.
-#ckan.redis.url = redis://localhost:6379/0
+ckan.redis.url = redis://ubu18:6379/0


## CORS Settings
@@ -119,7 +119,7 @@
# Add ``datapusher`` to enable DataPusher
# Add ``resource_proxy`` to enable resorce proxying and get around the
# same origin policy
-ckan.plugins = stats text_view image_view recline_view
+ckan.plugins = stats text_view image_view recline_view datastore datapusher

# Define which views should be created by default
# (plugins must be loaded in ckan.plugins)
@@ -181,7 +181,7 @@

# Make sure you have set up the DataStore

-#ckan.datapusher.formats = csv xls xlsx tsv application/csv application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
+ckan.datapusher.formats = csv xls xlsx tsv application/csv application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
#ckan.datapusher.url = http://127.0.0.1:8800/
#ckan.datapusher.assume_task_stale_after = 3600

@@ -206,7 +206,7 @@

#email_to = errors@example.com
#error_email_from = ckan-errors@example.com
-#smtp.server = localhost
+smtp.server = ubu18
#smtp.starttls = False
#smtp.user = username@example.com
#smtp.password = your_password

↑の変更点を説明する。

まず、今回はVM上のDockerで起動したので、SSHトンネル経由でのアクセスで困らないように開発環境ホスト名を localhost から変更した。

また、Datastore機能、Datapusher機能を利用するためにプラグインを追加。

Datapusherのフォーマットを有効化(コメントアウトを解除)

コンテナを再起動。

1
$ docker-compose restart

公式サイトに記載の通り、APIに試しにアクセスるとレスポンスがあるはず。

1
$ curl 'http://localhost:5000/api/3/action/datastore_search?resource_id=_table_metadata'

アドミンユーザ作成。

1
$ docker exec -it ckan /usr/local/bin/ckan -c /etc/ckan/production.ini sysadmin add johndoe

http://<サイトのurl>/ckan にアクセスすれば、ウェブUIが確認できる。 先に設定した、アドミンユーザでとりあえずログインする。

データストアとしてMinIO環境を整える

MinIOのDocker を参考に、Dockerでサーバを立ち上げる。

1
$ docker run -p 9000:9000 -p 9001:9001 minio/minio server /data --console-address ":9001"

http://<立ち上げたインスタンス>:9000 でMinIOのウェブコンソールにアクセスできる。 特に設定していなければ、ID:minioadmin、パスワード:minioadminである。

MinIのUI
MinIのUI
MinIのUI

別のコンソールで mcクライアントを立ち上げる。

1
$ docker run --name my-mc --hostname my-mc -it --entrypoint /bin/bash --rm minio/mc

エイリアスを設定し、バケットを作成する。 (URLは、MinIO起動時にコンソールに表示されるAPI用のURLを利用すること)

1
2
# mc alias set myminio http://172.17.0.2:9000 minioadmin minioadmin
# mc mb myminio/mybucket

ファイルを作成し、MinIOにアップロード(コピー)する。

1
2
# echo "hoge" > /tmp/hoge.txt
# mc cp /tmp/hoge.txt myminio/mybucket/hoge.txt

AWS CLIでアクセスする

AWS CLI v2 Docker image を利用してAWS CLIを起動し、MinIOにアクセスする。 なお、コンテナで起動するのでそのままではホスト側の ~/.aws にアクセスできない。そこで -v オプションを利用しマウントしてから configure するようにしている。 また、S3プロトコルでアクセスする際には、今回は手元のMinIO環境を利用するため、エンドポイントを指定していることに注意。

1
2
3
$ docker run --rm -it -v ~/.aws:/root/.aws amazon/aws-cli configure --profile myminio
$ docker run --rm -it -v ~/.aws:/root/.aws amazon/aws-cli --profile myminio s3 --endpoint-url http://172.17.0.2:9000 ls s3://mybucket/hoge.txt
2022-01-21 16:38:19 5 hoge.txt

無事にS3プロトコルでアクセスできたことが確かめられた。

CKANのUIで操作

組織の作成

組織作成
組織作成
組織作成

データセット作成

データセット作成
データセット作成
データセット作成

先ほどのS3プロトコルURL( s3://mybucket/hoge.txt )を登録する。

(補足)初期化

何らかの理由でDockerの環境をまっさらに戻したいことがあるかもしれない。 その場合は以下の通り。

1
2
3
4
5
6
7
$ docker-compose down
$ docker rmi -f docker_ckan docker_db
$ docker rmi $(docker images -f dangling=true -q)
$ docker volume rm docker_ckan_config docker_ckan_home docker_ckan_storage docker_pg_data docker_solr_data
$ docker-compose build
$ docker-compose up -d
$ docker-compose restart ckan # give the db service time to initialize the db cluster on first run

(補足)FIWAREのCKANは拡張済?

FIWAREのCKAN の説明を見ると、Dataset登録時に Searchable のような項目がある。公式2.9.5で試したときにはなかった。 他にも Additional Info という項目があり、そこには OAuth-Token という項目もあった。 このように、特にアクセス管理や認証認可の機能が拡張されているのか、と思った。

インストール(パッケージ)

Ubuntu18環境にCKANをインストールする。 基本的には、 Installing CKAN from package に従う。

参考

CKAN

MinIO

AWS CLI

共有

Latency Guarantee of Stream Processing

メモ

ストリーム処理におけるレイテンシ保証の仕組みにどんなものがあるか調査したメモ。

ストリーム処理のレイテンシとして気にするべきは、

  • 正常時のレイテンシ
  • 故障発生時のリカバリ含むレイテンシ

が挙げられそうである。

特許

論文

レイテンシ保証の話ではないが、ウォーターマークに関する取り組みもある。 以下は、2021年の論文。

ソフトウェア

  • いわゆるタイムウィンドウ処理やウォータマークの仕組みは既存の ストリーム処理OSSに採用されている。

そのほか

参考

特許

論文

共有

Error about the memory configuration of Minikube

メモ

現状の結論(2022/1/10時点)

解決まで至ってはいなく、状況整理したのみ。

雑記

minikube 1.23 Your cgroup does not allow setting memory #12842 にも記載されているエラーが以下の環境で生じた。

環境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dobachi@ubu18:~$ minikube version
minikube version: v1.24.0
commit: 76b94fb3c4e8ac5062daf70d60cf03ddcc0a741b

dobachi@ubu18:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.6 LTS"

dobachi@ubu18:~$ uname -a
Linux ubu18 5.4.0-92-generic #103~18.04.2-Ubuntu SMP Wed Dec 1 16:50:36 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

dobachi@ubu18:~$ grep cgroup /proc/filesystems
nodev cgroup
nodev cgroup2

上記のIssueに記載されている通り、Minikubeでは、cgroupでメモリリミットを設定できるかどうかを確認する際、 以下のような関数を利用する。

oci.go#L111-L124

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func HasMemoryCgroup() bool {
memcg := true
if runtime.GOOS == "linux" {
var memory string
if cgroup2, err := IsCgroup2UnifiedMode(); err == nil && cgroup2 {
memory = "/sys/fs/cgroup/memory/memsw.limit_in_bytes"
}
if _, err := os.Stat(memory); os.IsNotExist(err) {
klog.Warning("Your kernel does not support memory limit capabilities or the cgroup is not mounted.")
memcg = false
}
}
return memcg
}

以下のファイルをstatしているのだが…

1
memory = "/sys/fs/cgroup/memory/memsw.limit_in_bytes"

これは上記環境では存在しない。

1
2
dobachi@ubu18:~$ sudo stat /sys/fs/cgroup/memory/memsw.limit_in_bytes
stat: '/sys/fs/cgroup/memory/memsw.limit_in_bytes' を stat できません: そのようなファイルやディレクトリはありません

一方、 /sys/fs/cgroup/memory/memory.soft_limit_in_bytes なら存在する。

1
2
3
4
5
6
7
8
9
dobachi@ubu18:~$ sudo stat /sys/fs/cgroup/memory/memory.soft_limit_in_bytes
File: /sys/fs/cgroup/memory/memory.soft_limit_in_bytes
Size: 0 Blocks: 0 IO Block: 4096 通常の空ファイル
Device: 23h/35d Inode: 11 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-01-10 21:39:31.409626300 +0900
Modify: 2022-01-10 21:39:31.409626300 +0900
Change: 2022-01-10 21:39:31.409626300 +0900
Birth: -

なお、 エラーメッセージにある通り、 Your kernel does not support cgroup swap limit capabilities にしたがってGRUP設定を変更・反映し、リブートしても状況は変わらない。

PodmanのIssueではあるが、関連する議論が podman unable to limit memory (-m flag) on Ubuntu/Debian distros #6365 に記載されている。

参考

共有

Blogs about the portability of kubernetes

メモ

このメモは、Kubernetesを利用することで以下のポータビリティを得られるのではないか、という点に関する議論を列挙したものである。

  • アプリケーションのポータビリティ
    • あるKubernetesクラスタ上にデプロイした or 可能なアプリケーションを異なるKubernetes環境で実行する
  • Kubernetesクラスタのポータビリティ
    • Kubernetesクラスタを様々な環境で実行する

Kubernetes を本番環境に適用するための Tips

Kubernetes を本番環境に適用するための Tips の中に、アプリケーションのポータビリティに関する議論が含まれている。 具体的には、

  • Kubernetes環境の違い
  • Kubernetesが同じバージョンでも機能の有効・無効、使える・使えないが異なる
  • Kubernetesのバージョンが異なると設定ファイルの書き方が同一である保証がない
  • 具体例として、LoadBalancerやVolumeが環境によって異なる

ことが挙げられた。

Kubernetes 8 Factors - Kubernetes クラスタの移行から学んだクラスタのポータビリティの重要性と条件

Kubernetes 8 Factors - Kubernetes クラスタの移行から学んだクラスタのポータビリティの重要性と条件 では、 KubernetesのBreaking Changeに関して言及されていた。 (アプリケーションのポータビリティの話もあるが、Kubernetesクラスタの運用に関する点が言及された記事)

そこそこの頻度(マイナーバージョンアップにおいても、という意味)でも、Breaking Changeが生じるため、アップデートしていくのが大変だ、と。 小さな規模だったらクラスタ丸ごとデプロイしなおす(※)、という対応も可能だったが、様々な業務が載ってくるとそれも大変、と。

※小さな規模でクラスタ丸ごと都度デプロイしなおす、ということだと、Kubernetesで抽象化する意味が…?ということも考えうるか?

Twelve-Factor App

Twelve-Factor App にはアプリケーションのポータビリティの考えを含む、以下のような「Software as a Service 」を実現するにあたってのポイントが提言されている。

  • セットアップ自動化のために 宣言的な フォーマットを使い、プロジェクトに新しく加わった開発者が要する時間とコストを最小化する。
  • 下層のOSへの 依存関係を明確化 し、実行環境間での 移植性を最大化 する。
  • モダンな クラウドプラットフォーム 上への デプロイ に適しており、サーバー管理やシステム管理を不要なものにする。
  • 開発環境と本番環境の 差異を最小限 にし、アジリティを最大化する 継続的デプロイ を可能にする。
  • ツール、アーキテクチャ、開発プラクティスを大幅に変更することなく スケールアップ できる。

Kubernetesを採用するべき12の理由

Kubernetesを採用するべき12の理由 にはアプリケーションのポータビリティに関連するKubernetesの利点が記載されている。 一部、Kubernetesクラスタのポータビリティと考えてもよい内容もある。

理由4 仮想サーバーやベアメタルとハイブリッド構成可能な柔軟な運用基盤

理由6 オンプレとクラウドの両方で利用できる運用基盤

Kubernetes、やめました

ポータビリティの直接的な議論ではないが、Kubernetes、やめました にはKubernetesを採用しなかったケースの話が記載されている。 Kubernetesの学習コストと効果を天秤にかけた結果、他の技術で目的は達成できるはず、ということ。

多分あなたにKubernetesは必要ない

多分あなたにKubernetesは必要ない では、KubernetesではなくNomadを利用することにした経緯が記載されている。 Nomadは「オーケストレータ」だがそれで用が足りた、ということのようだ。

もしあなたが大規模インフラ上に同一サービス群をデプロイする計画をしているのであれば、Kubernetesという道を選んで良いでしょう。ただ、複雑性や運用コストが増えることを肝に命じてください。そしてこういったコストの一部は、Google Kubernetes EngineやAmazon EKSのようなマネージドKubernetes環境を利用することで省くことができます。

「あなたにKubernetesは必要ですか?」を、Kubernetes Meetup Tokyoのコアメンバーが議論

「あなたにKubernetesは必要ですか?」を、Kubernetes Meetup Tokyoのコアメンバーが議論 では、 多分あなたにKubernetesは必要ない の記事を受けて行われた、 日本でKubernetesを本格運用している企業の著名エンジニアによるパネルディスカッションの様子が記載されている。

なお、個人的に気になったのは以下の下り。

青山氏は、Kubernetesでも、CI/CDツールなどとうまく組み合わせることで、カスタマイズできるPaaSに近い環境を作ることができるとした。また、五十嵐氏は、「開発者と運用支援担当が別チームとして役割分担しやすい」というKubernetesの特徴を生かせれば、開発者が最小限の設定で使えるようにできると話した。

ルイス氏は、Kubernetes上でPaaSやFaaSが稼働するような動きが今後進むことで、一部の懸念は解消に向かうのではないかとしている。

PaaSやFaaSを実現する基盤技術は、単体でクラスタ構成可能なものもあるため、Kubernetes上に載せることで「抽象化の層」が増えることになる。 抽象化の恩恵と複雑性増加の辛さを天秤にかけることになるだろう。

CNDO2021、Kubernetesがない世界とある世界の違いをインフラエンジニアが解説

ポータビリティはあまり関係ない。

CNDO2021、Kubernetesがない世界とある世界の違いをインフラエンジニアが解説 では、 「CI/CDまではできているがKubernetesがない」場合と、Kubernetesがある場合を比較し、 「Kubernetesがなくてもクラウドネイティブ化の目的は達成できうるが、結局はKubernetesらが実現していることを自分でやらないといけない」とした。

なお、クラウドネイティブ化の目的については、CNCFの定義が引用されていた。

素早く継続的にユーザーに価値を届ける

参考

共有

Getting started Spark on k8s

メモ

このメモは、Spark3.2.0をKubernetes上で動かすことを簡単に紹介するものである。 なお、日本語での説明としては、 Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料) がとても分かりやすいので参考になる。

基本的な流れ

公式の Running Spark on Kubernetes の通りでよい。

ビルド

まずは、パッケージに含まれているDockerfileを利用して、Dockerイメージを自分でビルドする。 今回はMinikube環境で動かしているので -m オプションを利用した。

簡易的な例

1
$ /opt/spark/default/bin/docker-image-tool.sh -m -t testing build

Minikube内のDockerでイメージ一覧を確認すると以下の通り。

1
2
3
4
5
$ eval $(minikube -p minikube docker-env)
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
spark testing e19cebbf23e7 44 minutes ago 602MB
(snip)

実行

サービスアカウントを作る。

1
2
3
4
5
6
$ minikube kubectl -- create serviceaccount spark
$ minikube kubectl -- create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default
$ minikube kubectl -- get serviceaccount
NAME SECRETS AGE
default 1 179m
spark 1 2m39s

実行は以下の通り。先ほど作ったサービスアカウントを使用するようにする。

1
$ /opt/spark/default/bin/spark-submit --master k8s://https://192.168.49.2:8443 --deploy-mode cluster --name pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=spark:testing --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark local:///opt/spark/examples/jars/spark-examples_2.12-3.2.0.jar

なお、今回はMinikube上で実行しており、Jarファイルとして指定するのはMinikube内で起動したドライバのコンテナ内のローカルファイルシステムパスである。試しに、当該近店をアタッチして起動するとわかる。

ドライバのログを確認する。

1
2
3
4
5
6
7
8
$ minikube kubectl -- logs pi-43bff77e450bdba3-driver
(snip)
22/01/10 17:32:02 INFO TaskSchedulerImpl: Killing all running tasks in stage 0: Stage finished
22/01/10 17:32:02 INFO DAGScheduler: Job 0 finished: reduce at SparkPi.scala:38, took 0.824388 s
Pi is roughly 3.142475712378562
22/01/10 17:32:02 INFO SparkUI: Stopped Spark web UI at http://pi-43bff77e450bdba3-driver-svc.default.svc:4040
22/01/10 17:32:02 INFO KubernetesClusterSchedulerBackend: Shutting down all executors
(snip)

pi計算の結果がログに出力されているのがわかる。

(補足)ビルドされたイメージを起動して内容確認

以下は、MinikubeのDockerを利用しビルドしたイメージのコンテナを起動して、シェルをアタッチした例。

1
2
$ eval $(minikube -p minikube docker-env)
$ docker run -it --rm spark:testing /bin/bash

(補足)Minikube使う場合のリソース設定についての注意事項

Prerequisites の通り、Minikube等を使うようであれば、リソースに対して注意がある。 以下、Minikube立ち上げ例。

1
$ minikube start --memory='4g' --cpus=3

(補足)Kubernetes環境

動作確認のためには、Kubernetes環境が必要である。

minikube start あたりを参考に環境構築しておくこと。

(補足)ボリュームのマウントについて

volume-mounts の通り、DriverやExecutorのPodにボリュームをマウントできるのだが、 HostPathに関するリスクがあるようだ。 KubernetesのhostPathについて を参照。

(補足)上記例ではサービスアカウントを作成しているが・・・

もし default サービスアカウントを利用すると以下に記載されたのと同様のエラーを生じる。

How to fix "Forbidden!Configured service account doesn't have access" with Spark on Kubernetes?

そこで、あらかじめサービスアカウントを作成して使うようにした。

参考

共有

Delta Sharing with MinIO

メモ

Delta SharingはAWS S3、Azure Blob Storage、Azure Data Lake Storage Gen2に対応している。 そこで、AWS S3互換のストレージソフトウェアだったら使えるのではないか、ということで、 MinIO を利用してみることにする。

もろもろのサンプルコードは dobachi DeltaSharingMinioExample にある。

MinIOの起動

MinIO Quickstart Guide を参考に、手元でMinIOサーバを構成する。 以下は手順の一例。

バイナリをダウンロードし、データ保存ディレクトリを作って立ち上げる。

1
2
3
4
5
6
$ mkdir -p ~/Minio
$ cd ~/Minio
$ wget https://dl.min.io/server/minio/release/linux-amd64/minio
$ mkdir -p data
$ chmod +x minio
$ ./minio server data

コンソールにメッセージが色々出る。 今回はテスト用なので特段指定しなかったが、Rootユーザの名称、パスワードが表示されているはずである。 これは後ほど、AWS S3プロトコルでMinIOサービスにアクセスする際のID、シークレットキーとしても利用する。

MinIOのクライアントをダウンロードし、エイリアスを設定する。 別のターミナルを開く。

1
2
3
4
$ cd ~/Minio
$ wget https://dl.min.io/client/mc/release/linux-amd64/mc
$ chmod +x mc
$ ./mc alias set myminio http://your_host:9000 minioadmin minioadmin

your_hostのところは各自の環境に合わせて変更してほしい。 これにより、myminio という名前でエイリアスが作成された。

ちなみに、http://your_host:40915/ からアクセスできる。

なお、試しにAWS S3クライアントで接続してみることにする。

1
2
3
4
5
6
7
$ ./mc mb data/test_bucket
$ echo 'test' > test.txt
$ export AWS_ACCESS_KEY_ID=minioadmin
$ export AWS_SECRET_ACCESS_KEY=minioadmin
$ aws --endpoint-url http://localhost:9000 s3 ls
2021-10-22 12:26:13 test_bucket
$ aws --endpoint-url http://localhost:9000 s3 cp test.txt s3://test_bucket/test.txt

ここで、今回はMinioを利用していることから、エンドポイントURLを指定していることに注意。

テストバケットに入ったデータ

Delta Sharingサーバの起動

Delta Sharing Reference Server を参考に、サーバを起動する。

リリースされたパッケージを利用する場合

パッケージを公式リリースからダウンロードして展開する。

1
2
3
4
5
$ mkdir -p ~/DeltaSharing
$ cd ~/DeltaSharing
$ wget https://github.com/delta-io/delta-sharing/releases/download/v0.2.0/delta-sharing-server-0.2.0.zip
$ unzip delta-sharing-server-0.2.0.zip
$ cd delta-sharing-server-0.2.0

現在のmainブランチを利用する場合

1
2
3
4
5
$ mkdir -p ~/Sources/
$ cd ~/Sources
$ git clone git@github.com:delta-io/delta-sharing.git
$ delta-sharing
$ ./build/sbt server/universal:packageBin

server/target/universal/delta-sharing-server-x.y.z-SNAPSHOT.zip にパッケージが保存される。 なお、x.y.zにはバージョン情報が入る。ここでは0.3.0とする。

1
2
3
4
$ cp server/target/universal/delta-sharing-server-x.y.z-SNAPSHOT.zip ~/DeltaSharing/
$ cd ~/DeltaSharing/
$ unzip delta-sharing-server-0.3.0-SNAPSHOT.zip
$ cd delta-sharing-server-0.3.0-SNAPSHOT

設定ファイルの作成

Delta Sharingはデータストアのアクセスについて、間接的にHadoopライブラリに依存している。 そこで、AWS S3プロトコルでアクセスするためのHadoop設定ファイル core-site.xml を作成する。

conf/core-site.xml

1
2
3
4
5
6
7
8
9
10
<configuration>
<property>
<name>fs.s3a.endpoint</name>
<value>http://localhost:9000</value>
</property>
<property>
<name>fs.s3a.path.style.access</name>
<value>true</value>
</property>
</configuration>

ここではエンドポイントURL、パス指定方法の設定をしている。 なおパス指定方法の設定行わないと、Delta SharingからMinIOサーバにリクエストを送る際に、 ホスト名が bucket_name.host のような指定になってしまい、 400 But Reuqest エラーを生じてしまう。 詳しくは、 トラブルシュートの節を参照。

続いて、Delta Sharingサーバの設定ファイルを作成する。 以下は参考。

conf/delta-sharing-server.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# The format version of this config file
version: 1
# Config shares/schemas/tables to share
shares:
- name: "share1"
schemas:
- name: "schema1"
tables:
- name: "table1"
location: "s3a://test_bucket/delta_table"
# Set the host name that the server will use
host: "localhost"
# Set the port that the server will listen on
port: 18080
# Set the url prefix for the REST APIs
endpoint: "/delta-sharing"
# Set the timeout of S3 presigned url in seconds
preSignedUrlTimeoutSeconds: 900
# How many tables to cache in the server
deltaTableCacheSize: 10
# Whether we can accept working with a stale version of the table. This is useful when sharing
# static tables that will never be changed.
stalenessAcceptable: false
# Whether to evaluate user provided `predicateHints`
evaluatePredicateHints: false

ここで s3a://test_bucket/delta_table に指定しているのがMinIO内のデータである。 ここでは予め Delta Lakeフォーマットのデータを保存してあるものとする。

Delta Sharingサーバの起動

1
$ ./bin/delta-sharing-server -- --conf conf/delta-sharing-server.yaml

Delta SharingのPythonクライアントを利用してアクセスする。

まずクライアント用のプロファイルを準備する。

minio.share

1
2
3
4
5
{
"shareCredentialsVersion": 1,
"endpoint": "http://localhost:18080/delta-sharing/",
"bearerToken": ""
}

これを利用しながら、テーブルにアクセスする。

Delta Sharingのクライアントでアクセス

ここでは試しにPandas DataFrameとして読み取っている。

トラブルシュート

パス指定方法の誤り

Hadoop設定上で、パス指定方法の設定を行わないと、以下のようなエラーが生じる。

Delta Sharingサーバ側のエラー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Caused by: org.apache.hadoop.fs.s3a.AWSS3IOException: doesBucketExist on test: com.amazonaws.services.s3.model.AmazonS3Exception: Bad Request (Service: Amazon S3; Status Code: 400; Error Code: 400 Bad Request; Request ID: null; S3 Extended Request ID: null), S3 Extended Request ID: null: Bad Request (Service: Amazon S3; Status Code: 400; Error Code: 400 Bad Request; Request ID: null; S3 Extended Request ID: null)
at org.apache.hadoop.fs.s3a.S3AUtils.translateException(S3AUtils.java:194)
at org.apache.hadoop.fs.s3a.S3AFileSystem.verifyBucketExists(S3AFileSystem.java:335)
at org.apache.hadoop.fs.s3a.S3AFileSystem.initialize(S3AFileSystem.java:280)
at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3247)
at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:121)
at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:3296)
at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:3264)
at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:475)
at org.apache.hadoop.fs.Path.getFileSystem(Path.java:356)
at io.delta.standalone.internal.DeltaSharedTable.$anonfun$deltaLog$1(DeltaSharedTableLoader.scala:76)
at io.delta.standalone.internal.DeltaSharedTable.withClassLoader(DeltaSharedTableLoader.scala:95)
at io.delta.standalone.internal.DeltaSharedTable.<init>(DeltaSharedTableLoader.scala:74)
at io.delta.standalone.internal.DeltaSharedTableLoader.$anonfun$loadTable$1(DeltaSharedTableLoader.scala:53)
at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4693)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3445)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2194)
... 60 more

Minioサーバ側でのエラー

1
$ ./mc admin trace myminio --debug -v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
test.localhost:9000 [REQUEST methodNotAllowedHandler.func1] [2021-10-22T03:57:08:000] [Client IP: 127.0.0.1]
test.localhost:9000 HEAD /
test.localhost:9000 Proto: HTTP/1.1
test.localhost:9000 Host: test.localhost:9000
test.localhost:9000 Amz-Sdk-Invocation-Id: 821962e2-e1f8-31d7-4d0d-431529a3725c
test.localhost:9000 Authorization: AWS4-HMAC-SHA256 Credential=minioadmin/20211022/us-east-1/s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=07977380f3fd92b149e8c60937554fc5ee5287a0863c101431ef51aa3968c37b
test.localhost:9000 Connection: Keep-Alive
test.localhost:9000 Content-Type: application/octet-stream
test.localhost:9000 X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
test.localhost:9000 Amz-Sdk-Retry: 0/0/500
test.localhost:9000 Content-Length: 0
test.localhost:9000 User-Agent: Hadoop 2.10.1, aws-sdk-java/1.11.271 Linux/4.19.104-microsoft-standard OpenJDK_64-Bit_Server_VM/11.0.12+7-LTS java/11.0.12 scala/2.12.10
test.localhost:9000 X-Amz-Date: 20211022T035708Z
test.localhost:9000
test.localhost:9000 [RESPONSE] [2021-10-22T03:57:08:000] [ Duration 66µs ↑ 137 B ↓ 375 B ]
test.localhost:9000 400 Bad Request
test.localhost:9000 Content-Type: application/xml
test.localhost:9000 Server: MinIO
test.localhost:9000 Vary: Origin
test.localhost:9000 Accept-Ranges: bytes
test.localhost:9000 Content-Length: 261
test.localhost:9000 <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>BadRequest</Code><Message>An error occurred when parsing the HTTP request HEAD at &#39;/&#39;</Message><Resource>/</Resource><RequestId></RequestId><HostId>baec9ee7-bfb0-441b-a70a-493bfd80d745</HostId></Error>

参考

MinIO

Delta Sharing

Sample code

共有