kakts-log

programming について調べたことを整理していきます

Docker Servicesまとめ

概要

前記事

Docker containerまとめ - kakts-log

に引き続き Docker公式ドキュメントのPart3 Servicesの内容を整理します.

Part3 Services

Introduction

パート3では、アプリケーションのスケールを行い,ロードバランシングを有効にさせます.
これを行うために,アプリケーションのヒエラルキーの一段上のレベル,Serviceについて取り上げます.

  • Stack
  • Services
  • Container

About services

分散化されたアプリケーションにおいて,分散化された各ピースのことを"Services"と呼びます.
たとえば,もし動画のシェアリングサイトを考えたときに,おそらくアプリケーションはデータベースにアプリケーションを保存するServiceを含むのと,ユーザがアップロードしたあとにバックグラウンドで動画をトランスコードするServiceや,フロントエンドのServiceが考えられます.

Servicesは実際にはただの本番環境でのコンテナ群として扱われます.
単一のServiceは,1つのイメージを実行しますが,イメージをどのように実行するかを明文化します.
たとえば,どのポートを使うか,Serviceがキャパシティを担保するためにいくつのコンテナレプリカを実行するかなどです.
Serviceのスケーリングを行う場合は,コンテナの数を変更し,そのServiceに対して使うリソースを増やします.

Your first docker-compose.yml file

docker-compose.yml ファイルはYAML形式のファイルで,Dockerコンテナがプロダクション環境でどのように振る舞うかを定義します.

docker-compose.yml

docker-compose.yml というファイルを作成して,使っているディレクトリの直下に保存します.

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"
    networks:
      - webnet
networks:
  webnet:

内容は上記になります.具体的には以下の内容でコンテナを起動するように指定しています.

  • Part2で使ったイメージをpullしてくる
  • webというService名で,5つのコンテナインスタンスを起動する. 各コンテナは最大でも10%のCPUリソースと50MBのRAMを使用します.
  • もしコンテナが落ちた場合すぐに再起動させる.
  • ホストマシンの80番ポートをwebのポート80に対応させる.
  • webのコンテナに対して,webnetと呼ばれるロードバランシングネットワークを介して80番ポートを共有させる. (内部的には,各コンテナは80番のエフェメラルポートとしてパブリッシュする)
  • webnetネットワークを初期設定で定義する.

Run your new load-balanced app

docker stack deploy コマンドを実行する前に,下記コマンドを実行します.

docker swarm init

詳細はPart4で解説します.

ここでdocker stack deployコマンドを実行します .

docker stack deploy -c docker-compose.yml getstartedlab

これにより,docker-compose.yml で指定した内容をもとにServiceが起動します.

docker service ls で,立ち上げたServiceの一覧を確認できます.

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                     PORTS
iji3jgsi3i80        getstartedlab_web   replicated          5/5                 username/get-started:part2   *:80->80/tcp

NAME項目をみると,指定したアプリ名がService名(web)の先頭に付加され,getstartedlab_webとなっているのがわかります.

ロードバランシングされるので,ホストマシンのブラウザでlocalhost:80でアクセスするとコンテナにアクセスされ,アクセス毎にHostnameが変わることを確認できます.

さらにdocker ps で実際に立ち上がったコンテナが5つあることを確認できます.

$ docker ps
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS              PORTS               NAMES
c39d05ca95fe        username/get-started:part2   "python app.py"     7 seconds ago       Up 3 seconds        80/tcp              getstartedlab_web.3.xievdky2mkx38pl1foa68tzcg
002d8fe2434d        username/get-started:part2   "python app.py"     7 seconds ago       Up 3 seconds        80/tcp              getstartedlab_web.2.z17cyc4kcavu21o6cu2pxtjfl
a959c1870f87        username/get-started:part2   "python app.py"     7 seconds ago       Up 4 seconds        80/tcp              getstartedlab_web.1.xghoiespwuc5wu2oxqn52xxhh
eebff64dc8ac        username/get-started:part2   "python app.py"     7 seconds ago       Up 4 seconds        80/tcp              getstartedlab_web.4.y0vvq8sjj8xzau3meq98fbpfm
4ba7a3c03f56        username/get-started:part2   "python app.py"     7 seconds ago       Up 4 seconds        80/tcp              getstartedlab_web.5.a57ejflvl0k1ckpqs5jvu33v7

docker service ps ${service_name} でサービスに紐付いたコンテナのみを表示することもできます.

Scale the app

docker-compose.yml 内のreplicas項目を変更することで,アプリケーションをスケールできます.
変更した後,再度docker stack deploy コマンドを実行することで再起動できます.
今回はreplicasを7に変更した上で再起動します.

docker stack deploy -c docker-compose.yml getstartedlab_web

再起動後,コンテナが7つ起動しているのを確認できます.

$ docker container ls
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS              PORTS               NAMES
ff8a37fa9377        username/get-started:part2   "python app.py"     18 seconds ago      Up 17 seconds       80/tcp              getstartedlab_web.6.umd3i06tcfq1jkeh64znr53uv
fc5150a8b9ee        username/get-started:part2   "python app.py"     18 seconds ago      Up 16 seconds       80/tcp              getstartedlab_web.7.q6kbemo6ghgjh7v45amsvcwzn
c39d05ca95fe        username/get-started:part2   "python app.py"     15 minutes ago      Up 15 minutes       80/tcp              getstartedlab_web.3.xievdky2mkx38pl1foa68tzcg
002d8fe2434d        username/get-started:part2   "python app.py"     15 minutes ago      Up 15 minutes       80/tcp              getstartedlab_web.2.z17cyc4kcavu21o6cu2pxtjfl
a959c1870f87        username/get-started:part2   "python app.py"     15 minutes ago      Up 15 minutes       80/tcp              getstartedlab_web.1.xghoiespwuc5wu2oxqn52xxhh
eebff64dc8ac        username/get-started:part2   "python app.py"     15 minutes ago      Up 15 minutes       80/tcp              getstartedlab_web.4.y0vvq8sjj8xzau3meq98fbpfm
4ba7a3c03f56        username/get-started:part2   "python app.py"     15 minutes ago      Up 15 minutes       80/tcp              getstartedlab_web.5.a57ejflvl0k1ckpqs5jvu33v7

Take down the app and the swarm

アプリケーションを停止する場合docker stack rmコマンドを実行します.

docker stack rm getstartedlab

実行後,Serviceが削除されていることを確認できます.

$ docker service ps getstartedlab_web
no such service: getstartedlab_web

swarmを停止する場合は以下のコマンドを実行します.

docker swarm leave --force

以上です. このようにDockerを使ったアプリケーションのスケールは非常に簡単です.

Docker containerまとめ

概要

前記事に引き続き Docker公式ドキュメントのPart2の内容を整理

Part2 containers

Introduction

Dockerの方式でアプリをビルドしていく.
アプリケーションのヒエラルキーの下層部分であるコンテナから始めます.

コンテナの上層はserviceと呼ばれ、production環境でコンテナがどのように振る舞うのかを定義します. (Part3で取り上げる).
ヒエラルキーの最上層はスタックと呼ばれ、全てのserviceのやり取りを定義します.(Part5で取り上げる).
- Stack
- Services
- Container(このパートで取り上げる)

Your new develop environment

今まで,もしPythonアプリケーションを作る際に、まず最初にマシン上にPythonのランタイムをインストールしていました.
しかし,このやり方はマシンの環境が作成するアプリを期待通りに動作させる必要を生じさせた.

Dockerで、ユーザはイメージとして可搬性のあるPythonランタイムを利用できます.
これにより,ユーザが作成するビルドはアプリケーションコードと同様にPythonイメージも含むことができ,ランタイムと依存関係を全て保証できます.

Define a container with Dockerfile

Dockerfile はコンテナ内の環境で起こることを定義します.
ネットワーク・インタフェースへのアクセスと,ディスクドライブはこの環境内で仮想化され,システム内の他のものとは隔離されるため,ユーザは外部とやり取りするためにポートを指定し,どのファイルをコンテナ環境内にコピーするか指定します.
指定したあと,Dockerfileで定義されたアプリがどのような環境でも正常に振る舞うことを保証されます.

Dockerfile

新たなディレクトリにDockerfileを作成し,簡単なPythonアプリの環境を定義する.

# Use an official Python runtime as a parent image
FROM python: 2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
Add . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this containers
EXPORSE 80

# Define environment variable
ENV NAME world

# Run app.py when the container launches
CMD ["python", "app.py"]

Dockerfile内にまだ作成されていないapp.pyrequirements.txtがあるので作成していきます.

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host = "redis", db = 0, socket_connect_timeout = 2, socket_timeout = 2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disbled</i?>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

pip install -r requirements.txt によってFlaskとRedisライブラリをインストールし,アプリケーションでは環境変数のNAMEを表示させています.

これで一通りアプリケーションに必要なファイルが揃いました.
ディレクトリ配下に3つのファイルがある状態となります.

$ ls
Dockerfile      app.py          requirements.txt

Build the app

これでアプリケーションをビルドする準備が整いました.
Dockerfileが存在しているディレクトリ上で,docker build コマンドを実行してDockerイメージを作成します. -tオプションにより,イメージ名を指定できます.

docker build -t friendlyhello .

作成後,Dockerイメージが作られたかを確認します.

$ docker image ls
REPOSITORY                TAG                 IMAGE ID            CREATED              SIZE
friendlyhello             latest              596560250ed9        About a minute ago   148MB

Run the app

ここでdocker run コマンドによりアプリケーションを起動させていきます. -pオプションで,マシン上の4000番ポートをコンテナ内の80番ポートと紐付けた上で起動させます.

$ docker run -p 4000:80 friendlyhello
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

ここで,マシン上のwebブラウザから,localhostの4000番ポートにアクセスするとアプリケーションへアクセスできます.

-dオプションを使うことでバックグラウンドでも実行できます.

docker run -d -p 4000:80 friendlyhello

docker container ls または docker ps で,使用しているコンテナのIDなどの情報をみることができます. ポートのマッピング情報なども見れます.

$ docker ps
CONTAINER ID        IMAGE                     COMMAND                CREATED             STATUS              PORTS                     NAMES
c2ee894e48ab        friendlyhello             "python app.py"        5 seconds ago       Up 4 seconds        0.0.0.0:4000->80/tcp      nostalgic_perlman

起動したコンテナプロセスを止める場合 docker container stop で行えます.
この際に止めたいコンテナのコンテナIDを指定します.

$ docker container stop c2ee894e48ab
c2ee894e48ab

Share your image

作成したコンテナイメージの可搬性を実感するために,コンテナイメージを外部にアップロードしてみます.
これを行う際に必要なのは,コンテナをデプロイする際にレジストリにプッシュする方法を知ることのみです.

レジストリはレポジトリのコレクションであり,,レポジトリはイメージのコレクションです.
レジストリのアカウント毎に多くのレポジトリを作成できます.
dockerクライアントはデフォルトで,docker公式レジストリを使用します.

Log in with your Docker ID

https://cloud.docker.com/ でアカウントを作成したうえで,dockerコマンドを使ってマシン上でレジストリにログインします.

$ docker login

Tag the image

レジストリ内のレポジトリの表記は username/repository:tag となります.
タグは必須ではないですが, つけることを推奨します. なぜならタグはレジストリのDockerイメージのバージョンを表す仕組みになっているからです.

レポジトリとタグ名はコンテキストに合わせた名前をつけるべきです.

ここで,実際にDockerイメージにタグを付けてみます.
以下のような表記でタグを作成できます.
username repository TAGはそれぞれユーザによって変えてください.

docker tag image username/repository:TAG

作成したタグは docker image ls で確認できます.

$ docker image ls
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
username/get-started         part2               16974e44583c        21 minutes ago      148MB

Publish the image

前項でDockerイメージに対するタグ付けができました.
ここで,タグをつけたDockerイメージをレポジトリにアップロードします.

docker push username/repository:TAG

アップロードしたイメージはパブリックに利用可能です.
Docker cloudにログインした上で下記のページで作成したイメージを確認できます.
https://hub.docker.com/

Pull and run the image from the remote repository

docker run コマンドでレポジトリとタグを直接指定してコンテナを起動することができます.

docker run -p 4000:80 username/repository:tag

もし指定したDockerイメージがローカルマシンに存在しない場合,DockerはレポジトリからDockerイメージをpullしてきます.

Docker Conceptまとめ

概要

DockerのConceptまわりを再度整理するために 公式ドキュメントのget-started part1の内容をメモ

docs.docker.com

1: Docker Concept

Docker: アプリケーションを開発・デプロイ・コンテナとして起動するプラットフォーム
linuxコンテナをアプリケーションにデプロイすることをコンテナ化と呼ぶ. コンテナ自体は新しいmのではないが、アプリケーションのデプロイが簡単になるために使われる.

コンテナ化はますます人気になっている理由はコンテナが以下のような性質を持つからである.
- フレキシブル 最も複雑なアプリケーションもコンテナ化できる.
- 軽量 コンテナはホストのカーネルを共用する
- 交換性 アプリケーションのデプロイが可能で、アップグレードも行える
- 可搬性 どこでも稼働する
- スケーラブル コンテナのレプリカを自動的に増やせる
- スタック可能 サービスを垂直的にスタック可能

Images and containers

コンテナはイメージを実行する事によって起動する.
イメージは実行可能なパッケージであり, アプリケーションを実行するためのコード,ライブラリや、環境変数,設定ファイルなどを全て含んでいる.

コンテナはイメージのインスタンスのランタイムであり、イメージの内容が実行されたときにメモリ内に格納されるものである.
docker ps コマンドを使って起動中のコンテナ一覧を見ることができます.

Containers and virtual machines

コンテナはlinux上で起動し、他のコンテナとホストマシンのカーネルを共有する.
コンテナは独立したプロセスを起動し、他の実行可能なプロセス以上にメモリを消費せず,軽量である.

それとは対照的に、VMはhypervisorを介して、ゲストOSを起動し、OSより上の層も全て含む.
通常,VMは多くのアプリケーションが実際に必要とするよりも多くのリソースを提供することとなる.

2: Containers

Kubernetesのコンセプトまとめ

Kubernetes コンセプト

Kubernetesのコンセプトを理解するために公式ドキュメントを読んでざっくり整理しました。

kubernetes.io

overview

kubernetesを利用するためには kubernetes apiを使ってクラスタを意図する構成にさせる。 たとえばどのようなアプリケーションやワークロードを使うか、使用するコンテナイメージ レプリカ数、ネットワークやディスクリソースの設定などです。

kubernetes apiは、 kubectlというコマンドラインインターフェースを通じて利用します。

  • The Kubernetes master: クラスタ内のシングルノード上でマスターノードとして起動する3つのプロセスのコレクションのこと。
    この3つのプロセスはkube-apiserver, kube-controller-manager, kube-schedulerです。

  • クラスタ上のマスターでないノードは2つのプロセスを起動します。
    kubelet: kubernetes masterとやり取りするプロセス
    kube-proxy: 各ノードにkubernetes networking serviceを反映させるネットワークプロキシ

Kubernetes Objects

Kubernetesはシステムの状態を表すために幾つかの抽象概念を持つ。
Kubernetes apiの内部でこれらの抽象概念はオブジェクトとして表現されます。
主なオブジェクトは以下のとおりです。

  • Pod
  • Service
  • Volume
  • Namespace

さらに、KubernetesはControllersと呼ばれる高レベルの抽象概念も持っています。 Controllersは上記の基本オブジェクトによって構成され、さらに便利な機能を提供します。
- ReplicaSet - Deployment - StatefulSet - DaemonSet - Job

Kubernetes Control Plane

Kubernetes MasterやKubelet プロセスのようなKubernetes Control Planeの様々なパーツは、Kubernetesとクラスタのコミュニケーションを統制します。
Control Planeはシステム内の全てのKUbernetes オブジェクトのレコードを管理し、そのオブジェクトの状態を管理するために継続的なループプロセスが稼働しています。
どんなときでも、Control Planeのループプロセスはクラスタ内の変更に応答し、システム内の全てのオブジェクトが意図する状態になるために稼働します。

Kubernetes Master

Kubernetes Masterはクラスタを意図する状態に維持します。 ユーザがkubectlコマンドを使ったりしてKubernetesとやり取りする際、ユーザはKubernetes Masterとやり取りする事となります。
"Master"はクラスタの状態をマネージするコレクションの集合を意味します。通常これらのプロセスはクラスタ内の単一ノード上で稼働し、そのノードは"Master"として扱われます。
Masterは可用性のためにレプリケーション可能です。

Kubernetes Nodes

クラスタ内のノードは、アプリケーションやワークフローを稼働させるマシン(VM 物理サーバなど)を意味します。
Kubernetes Masterはこれらの各ノードを管理し、ノード単体に対して直接操作することは殆どありません。

What is Ethereum? を読む

概要

この記事はブロックチェーン Advent Calendar 2017 - Qiita 9日目の記事です。

Ethereumについての勉強のため、公式ドキュメントの「What is Ethereum?」を翻訳しました。
What is Ethereum? — Ethereum Homestead 0.1 documentation

ところどころ解釈が不明瞭な箇所のもありますが、ご了承ください。

What is Ethereum?

Ethereumはオープンブロックチェーンネットワークであり、ブロックチェーンテクノロジによる非中央集権的なアプリケーションを誰でも構築・利用することを可能にします。
Bitcoinのように、世界中の多くのユーザによって作られたOSSプロジェクトであり、誰もEthereumをコントロールすることはできません。
しかし、Bitcoinとは違って、Ethereumはよりフレキシブルになっています。Ethereumプラットフォーム上で新たなアプリケーションの構築は非常に容易で、Homesteadリリース(Ethereum platformの2番目のメジャーバージョン)により、 誰でもこのアプリケーションを安全に使えます。

次世代のブロックチェーン

ブロックチェーンテクノロジはBitcoinの技術基盤で、2008年に謎の多い著者であるSatoshi Namamotoによるホワイトペーパー「Bitcoin: A Peer-to-Peer Electronic Cash System」で最初にコンセプトが著されました。
他の分野におけるブロックチェーンユースケースはこのホワイトペーパーで議論されていましたが、数年後にブロックチェーンは一般的な用語として登場しました。
ブロックチェーンは全てのネットワークノードが同一のトランザクションを実行し、記録する分散型コンピューティングアーキテクチャで、トランザクションはブロックとして扱われます。
一度に1ブロックだけ追加され、全てのブロックは前のブロックとつながっていることが数学的に証明するデータを保持しています。この方法で、ブロックチェーンの分散データベースはネットワーク全体のコンセンサスのもとに保持されます。

各ユーザのトランザクションは強固な暗号により守られています。ネットワークを維持し、トランザクションを処理するノードはプロトコル内に実装された数学的に証明されたインセンティブ方式によってインセンティブが付与されます。

Bitcoinにおけるケースでは、分散型データベースは各アカウントの残高、トランザクションを表したテーブルとして使われ、トランザクションBitcoinトークンの転送を意味し、信頼できない個人間でのファイナンスを促進します。
しかしBitcoinが技術者の注目を集める中、新規のプロジェクトでBitcoinを価値の転送以外の用途で使いはじめました。
これらの多くはBitcoinプロトコルの改良と、新機能を追加したalt-coinとして登場しました。
2013年後半、Ethereumの発明者であるVitalik Buterinは、任意の複雑な計算を実行するために再プログラムする機能を備えた単一のブロックチェーンが、これらの多くの他のプロジェクトを包含することを提案しました。

2014年、EthereumのファウンダーであるVitalik Buterin, Gavin Wood, Jeffrey Wilckeがより一般的であり、fully trustlessなスマートコントラクトプラットフォームを実装するという野望をもった次世代ブロックチェーンの開発に取り掛かりました。

Ethereum Virtual Machine

Ethreumはプログラム可能なブロックチェーンです。ユーザに最初から定義されたいくつかのオペレーションセットも提供し(例として、Bitcoinトランザクション)、Ethereumはユーザが独自のオペレーションを作ることを可能にします。
これにより、Ethereumは暗号通貨の他に、様々なタイプの非中央集権的ブロックチェーンアプリケーションのプラットフォームとなります。

Ethereumは狭義では、非中央集権的なアプリケーションのプラットフォームを定義する一連のプロトコルを意味します。 その中心たるものはEthereum Virtual Machine(EVM)と呼ばれ、任意の計算量をもつアルゴリズムを実行できます。
コンピュータサイエンスの用語でいうと、Ethereumは「チューリング完全」です。
開発者はJavascriptPythonをモデルとしたプログラミング言語でEVM上で動くアプリケーションを作ることができます。

他のブロックチェーンと同様に、Ethereumはpeer-to-peerのネットワークプロトコルを含みます。
Ethereumブロックチェーンデータベースはネットワークに接続された複数のノードにより、維持・アップデートされます。
ネットワーク内の全てのノードはEVMを実行し、同一のコードを実行します。これにより、Ethereumはときおり、"World Computer"として表現されます。

このEthereumネットワーク全体を通じて行われる巨大な並列計算は、計算を効率化されていません。
実際には、このプロセスはEthereumにおける計算をさらに遅くさせ、従来のコンピュータに比べてより高負荷になります。
むしろ、すべてのEthereumノードはブロックチェーンを通じたコンセンサスの維持のためにEVMを動かします。
非中央集権的コンサンサスは、Ethereumシステムの究極的なレベルの耐障害性、ゼロダウンタイムを保証し、ブロックチェーンに保存されたデータを永久に変更不可にし、検閲への耐久性も実現します。

Ethereumプラットフォームそれ自体は機能のない、価値のないものです。 プログラミング言語と同様に、そのシステムをどう使われるかは起業家や開発者に委ねられています。
しかし、1つ明らかなことは、あるタイプのアプリケーションはEthereumの機能によって、他のタイプよりも利益を得ることができるということです。
特に、Ethereumはネットワーク内のpeer間同士の直接的なやりとりと、グループ内の協調的行動の促進を自動化するようなアプリケーションに適しています。
例えば、peet-to-peerでの市場を運用したり、複雑な金融契約の自動化するアプリケーションなどがあげられます。
Bitcoinは個人間での通貨のやり取りを銀行や証券会社などの中間業者抜きで行えるようにしました。Ethereumの影響は、もっと大きなものになりえます。
理論的に、金融上のやりとりや計算処理は、Ehereum上で実行されているコードにより自動的かつ確実に実行できます。
金融系のアプリケーションだけでなく、信頼、セキュリティー、永続性が重要とされる全ての分野でEthereumプラットフォームは大きな影響を及ぼします。

How does Ethereum work?

Ethereumは、Bitcoinユーザに馴染みのある多くの機能を組み込んでおり、それらの機能に修正を加えたり、独自機能もあります。

Bitcoinブロックチェーンが純粋にトランザクションのリストである一方、Ethereumの基本単位はアカウントになります。
Ethereumブロックチェーンは全てのアカウントの状態をトラックしており、すべての状態遷移はアカウント間での価値と情報の移転を意味します。

外部アカウント(Externally owned accounts - EOSs) これらはプライベートキーによってコントロールされます

symbolic link (soft link)についてメモ

概要

Linuxプログラミングインタフェース18章2節の シンボリックリンクについて、学んだことのメモ

Linuxプログラミングインタフェース

Linuxプログラミングインタフェース

シンボリックリンクとは

シンボリックリンクとは、他のファイルのファイル名を自身のデータとして持つ特殊なファイル

シンボリックリンクは、ハードリンクとは異なるもので、参照先のファイルのリンクカウントには影響を与えない。
このため、参照先のファイルの情報を ls -liで確認しても、リンクカウントが増えない。

参照先ファイルが削除された場合、シンボリックリンク自体は残るが、参照先をたどることができなくなる。
このようなシンボリックリンクを danglink linkという。
また、最初から存在しないファイルを参照するようなシンボリックリンクも作成可能。

異なるファイルシステム間でのリンクについて

i-nodeは、同一ファイルシステム内のみ一意である。ハードリンクは、i-nodeを参照するため、異なるファイルシステム間のハードリンクはできないようになっている。 シンボリックリンクでは、参照するのはi-nodeでなくファイル名であるため、異なるファイルシステム上のファイルも参照できる。
さらに、ハードリンクではディレクトリに対する参照はできないが、シンボリックリンクではディレクトリを参照することができる。